bsv-sdk 0.19.1 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +89 -0
- data/README.md +2 -2
- data/lib/bsv/auth/transport.rb +1 -1
- data/lib/bsv/mcp/tools/broadcast_p2pkh.rb +5 -3
- data/lib/bsv/network/protocol.rb +4 -5
- 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 +6 -3
- data/lib/bsv/network/protocols/jungle_bus.rb +6 -0
- data/lib/bsv/network/protocols.rb +1 -0
- data/lib/bsv/network/provider.rb +7 -9
- 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/overlay/lookup_resolver.rb +0 -1
- data/lib/bsv/overlay/topic_broadcaster.rb +0 -1
- data/lib/bsv/primitives/curve.rb +1 -11
- data/lib/bsv/primitives/ecies.rb +1 -8
- data/lib/bsv/primitives/hex.rb +1 -1
- data/lib/bsv/script/script.rb +1 -1
- data/lib/bsv/transaction/beef.rb +0 -2
- data/lib/bsv/transaction/chain_tracker.rb +74 -13
- data/lib/bsv/transaction/chain_trackers/whats_on_chain.rb +3 -3
- data/lib/bsv/transaction/chain_trackers.rb +0 -10
- data/lib/bsv/transaction/fee_models/live_policy.rb +10 -8
- data/lib/bsv/transaction/merkle_path.rb +0 -2
- 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 +15 -8
- 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 +47 -3
- data/lib/bsv/transaction/chain_trackers/chaintracks.rb +0 -83
|
@@ -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 +verify_hmac+ call (call byte 14).
|
|
7
|
+
#
|
|
8
|
+
# Port of go-sdk/wallet/serializer/verify_hmac.go.
|
|
9
|
+
module VerifyHmac
|
|
10
|
+
HMAC_SIZE = 32
|
|
11
|
+
|
|
12
|
+
# Args wire layout:
|
|
13
|
+
# [key-related params]
|
|
14
|
+
# [32 bytes: HMAC]
|
|
15
|
+
# [VarInt data_len][data bytes]
|
|
16
|
+
# [optional_bool seek_permission]
|
|
17
|
+
module Args
|
|
18
|
+
module_function
|
|
19
|
+
|
|
20
|
+
def serialize(args)
|
|
21
|
+
hmac = Common.to_binary(args[:hmac])
|
|
22
|
+
raise BSV::Wallet::InvalidParameterError.new('hmac', "exactly #{HMAC_SIZE} bytes") unless hmac.bytesize == HMAC_SIZE
|
|
23
|
+
|
|
24
|
+
w = BSV::Wallet::Wire::Writer.new
|
|
25
|
+
Common.write_key_related_params(
|
|
26
|
+
w,
|
|
27
|
+
protocol_id: args[:protocol_id],
|
|
28
|
+
key_id: args[:key_id],
|
|
29
|
+
counterparty: args[:counterparty],
|
|
30
|
+
privileged: args[:privileged],
|
|
31
|
+
privileged_reason: args[:privileged_reason]
|
|
32
|
+
)
|
|
33
|
+
w.write_bytes(hmac)
|
|
34
|
+
data = Common.to_binary(args[:data])
|
|
35
|
+
w.write_varint(data.bytesize)
|
|
36
|
+
w.write_bytes(data)
|
|
37
|
+
w.write_optional_bool(args[:seek_permission])
|
|
38
|
+
w.buf
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def deserialize(bytes)
|
|
42
|
+
r = BSV::Wallet::Wire::Reader.new(bytes)
|
|
43
|
+
params = Common.read_key_related_params(r)
|
|
44
|
+
hmac = r.read_bytes(HMAC_SIZE)
|
|
45
|
+
data_len = r.read_varint
|
|
46
|
+
data = r.read_bytes(data_len)
|
|
47
|
+
seek_permission = r.read_optional_bool
|
|
48
|
+
params.merge(hmac: hmac, data: data, seek_permission: seek_permission)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Result wire layout: empty — success implies valid.
|
|
53
|
+
module Result
|
|
54
|
+
module_function
|
|
55
|
+
|
|
56
|
+
def serialize(_result)
|
|
57
|
+
''.b
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def deserialize(_bytes)
|
|
61
|
+
{ valid: true }
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BSV
|
|
4
|
+
module Wallet
|
|
5
|
+
module Serializer
|
|
6
|
+
# BRC-103 wire codec for the +verify_signature+ call (call byte 16).
|
|
7
|
+
#
|
|
8
|
+
# Port of go-sdk/wallet/serializer/verify_signature.go.
|
|
9
|
+
module VerifySignature
|
|
10
|
+
HASH_SIZE = 32
|
|
11
|
+
|
|
12
|
+
# Args wire layout:
|
|
13
|
+
# [key-related params]
|
|
14
|
+
# [optional_bool for_self]
|
|
15
|
+
# [VarInt sig_len][DER signature bytes]
|
|
16
|
+
# [1 byte: data-type flag — 1=data, 2=hash_to_directly_verify]
|
|
17
|
+
# If flag=1: [VarInt data_len][data bytes]
|
|
18
|
+
# If flag=2: [32 bytes: hash]
|
|
19
|
+
# [optional_bool seek_permission]
|
|
20
|
+
module Args
|
|
21
|
+
module_function
|
|
22
|
+
|
|
23
|
+
def serialize(args)
|
|
24
|
+
data = args[:data] && Common.to_binary(args[:data])
|
|
25
|
+
hash = args[:hash_to_directly_verify] && Common.to_binary(args[:hash_to_directly_verify])
|
|
26
|
+
sig = args[:signature] && Common.to_binary(args[:signature])
|
|
27
|
+
|
|
28
|
+
if data && hash
|
|
29
|
+
raise BSV::Wallet::InvalidParameterError.new(
|
|
30
|
+
'data and hash_to_directly_verify',
|
|
31
|
+
'not both provided — supply one or the other'
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
raise BSV::Wallet::InvalidParameterError.new('data or hash_to_directly_verify', 'present') unless data || hash
|
|
35
|
+
raise BSV::Wallet::InvalidParameterError.new('signature', 'present') unless sig
|
|
36
|
+
|
|
37
|
+
w = BSV::Wallet::Wire::Writer.new
|
|
38
|
+
Common.write_key_related_params(
|
|
39
|
+
w,
|
|
40
|
+
protocol_id: args[:protocol_id],
|
|
41
|
+
key_id: args[:key_id],
|
|
42
|
+
counterparty: args[:counterparty],
|
|
43
|
+
privileged: args[:privileged],
|
|
44
|
+
privileged_reason: args[:privileged_reason]
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
w.write_optional_bool(args[:for_self])
|
|
48
|
+
|
|
49
|
+
w.write_varint(sig.bytesize)
|
|
50
|
+
w.write_bytes(sig)
|
|
51
|
+
|
|
52
|
+
if data
|
|
53
|
+
w.write_byte(1)
|
|
54
|
+
w.write_varint(data.bytesize)
|
|
55
|
+
w.write_bytes(data)
|
|
56
|
+
else
|
|
57
|
+
w.write_byte(2)
|
|
58
|
+
w.write_bytes(hash)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
w.write_optional_bool(args[:seek_permission])
|
|
62
|
+
w.buf
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def deserialize(bytes)
|
|
66
|
+
r = BSV::Wallet::Wire::Reader.new(bytes)
|
|
67
|
+
params = Common.read_key_related_params(r)
|
|
68
|
+
for_self = r.read_optional_bool
|
|
69
|
+
sig_len = r.read_varint
|
|
70
|
+
signature = r.read_bytes(sig_len)
|
|
71
|
+
flag = r.read_byte
|
|
72
|
+
payload = case flag
|
|
73
|
+
when 1
|
|
74
|
+
len = r.read_varint
|
|
75
|
+
{ data: r.read_bytes(len) }
|
|
76
|
+
when 2
|
|
77
|
+
{ hash_to_directly_verify: r.read_bytes(HASH_SIZE) }
|
|
78
|
+
else
|
|
79
|
+
raise ArgumentError, "invalid data-type flag: #{flag}"
|
|
80
|
+
end
|
|
81
|
+
seek_permission = r.read_optional_bool
|
|
82
|
+
params.merge(for_self: for_self, signature: signature).merge(payload).merge(seek_permission: seek_permission)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Result wire layout: empty — success implies valid.
|
|
87
|
+
module Result
|
|
88
|
+
module_function
|
|
89
|
+
|
|
90
|
+
def serialize(_result)
|
|
91
|
+
''.b
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def deserialize(_bytes)
|
|
95
|
+
{ valid: true }
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BSV
|
|
4
|
+
module Wallet
|
|
5
|
+
# Registry of per-call BRC-103 binary serialisers.
|
|
6
|
+
#
|
|
7
|
+
# Each table maps a Wire::Calls constant to the module_function on the
|
|
8
|
+
# matching Serializer sub-module. Other developer agents populate their
|
|
9
|
+
# tiers in parallel — add one entry per call, one line each.
|
|
10
|
+
module Serializer
|
|
11
|
+
autoload :Common, 'bsv/wallet/serializer/common'
|
|
12
|
+
|
|
13
|
+
# Crypto tier (call bytes 8-16)
|
|
14
|
+
autoload :GetPublicKey, 'bsv/wallet/serializer/get_public_key'
|
|
15
|
+
autoload :RevealCounterpartyKeyLinkage, 'bsv/wallet/serializer/reveal_counterparty_key_linkage'
|
|
16
|
+
autoload :RevealSpecificKeyLinkage, 'bsv/wallet/serializer/reveal_specific_key_linkage'
|
|
17
|
+
autoload :Encrypt, 'bsv/wallet/serializer/encrypt'
|
|
18
|
+
autoload :Decrypt, 'bsv/wallet/serializer/decrypt'
|
|
19
|
+
autoload :CreateHmac, 'bsv/wallet/serializer/create_hmac'
|
|
20
|
+
autoload :VerifyHmac, 'bsv/wallet/serializer/verify_hmac'
|
|
21
|
+
autoload :CreateSignature, 'bsv/wallet/serializer/create_signature'
|
|
22
|
+
autoload :VerifySignature, 'bsv/wallet/serializer/verify_signature'
|
|
23
|
+
|
|
24
|
+
# Trivial tier (call bytes 23-28)
|
|
25
|
+
autoload :GetNetwork, 'bsv/wallet/serializer/get_network'
|
|
26
|
+
autoload :GetVersion, 'bsv/wallet/serializer/get_version'
|
|
27
|
+
autoload :GetHeight, 'bsv/wallet/serializer/get_height'
|
|
28
|
+
autoload :GetHeaderForHeight, 'bsv/wallet/serializer/get_header_for_height'
|
|
29
|
+
autoload :IsAuthenticated, 'bsv/wallet/serializer/status'
|
|
30
|
+
autoload :WaitForAuthentication, 'bsv/wallet/serializer/status'
|
|
31
|
+
autoload :CreateActionArgs, 'bsv/wallet/serializer/create_action_args'
|
|
32
|
+
autoload :CreateActionResult, 'bsv/wallet/serializer/create_action_result'
|
|
33
|
+
autoload :SignActionArgs, 'bsv/wallet/serializer/sign_action_args'
|
|
34
|
+
autoload :SignActionResult, 'bsv/wallet/serializer/sign_action_result'
|
|
35
|
+
autoload :AbortAction, 'bsv/wallet/serializer/abort_action'
|
|
36
|
+
autoload :InternalizeActionArgs, 'bsv/wallet/serializer/internalize_action'
|
|
37
|
+
autoload :InternalizeActionResult, 'bsv/wallet/serializer/internalize_action'
|
|
38
|
+
autoload :ListActionsArgs, 'bsv/wallet/serializer/list_actions'
|
|
39
|
+
autoload :ListActionsResult, 'bsv/wallet/serializer/list_actions'
|
|
40
|
+
autoload :Certificate, 'bsv/wallet/serializer/certificate'
|
|
41
|
+
autoload :DiscoverCertificatesResult, 'bsv/wallet/serializer/discover_certificates_result'
|
|
42
|
+
autoload :ListOutputs, 'bsv/wallet/serializer/list_outputs'
|
|
43
|
+
autoload :RelinquishOutput, 'bsv/wallet/serializer/relinquish_output'
|
|
44
|
+
autoload :AcquireCertificate, 'bsv/wallet/serializer/acquire_certificate'
|
|
45
|
+
autoload :ListCertificates, 'bsv/wallet/serializer/list_certificates'
|
|
46
|
+
autoload :ProveCertificate, 'bsv/wallet/serializer/prove_certificate'
|
|
47
|
+
autoload :RelinquishCertificate, 'bsv/wallet/serializer/relinquish_certificate'
|
|
48
|
+
autoload :DiscoverByIdentityKey, 'bsv/wallet/serializer/discover_by_identity_key'
|
|
49
|
+
autoload :DiscoverByAttributes, 'bsv/wallet/serializer/discover_by_attributes'
|
|
50
|
+
|
|
51
|
+
# Client-side: serialise outgoing args for each call.
|
|
52
|
+
SERIALIZE_ARGS = {
|
|
53
|
+
Wire::Calls::GET_PUBLIC_KEY => GetPublicKey::Args.method(:serialize),
|
|
54
|
+
Wire::Calls::REVEAL_COUNTERPARTY_KEY_LINKAGE => RevealCounterpartyKeyLinkage::Args.method(:serialize),
|
|
55
|
+
Wire::Calls::REVEAL_SPECIFIC_KEY_LINKAGE => RevealSpecificKeyLinkage::Args.method(:serialize),
|
|
56
|
+
Wire::Calls::ENCRYPT => Encrypt::Args.method(:serialize),
|
|
57
|
+
Wire::Calls::DECRYPT => Decrypt::Args.method(:serialize),
|
|
58
|
+
Wire::Calls::CREATE_HMAC => CreateHmac::Args.method(:serialize),
|
|
59
|
+
Wire::Calls::VERIFY_HMAC => VerifyHmac::Args.method(:serialize),
|
|
60
|
+
Wire::Calls::CREATE_SIGNATURE => CreateSignature::Args.method(:serialize),
|
|
61
|
+
Wire::Calls::VERIFY_SIGNATURE => VerifySignature::Args.method(:serialize),
|
|
62
|
+
Wire::Calls::GET_NETWORK => GetNetwork::Args.method(:serialize),
|
|
63
|
+
Wire::Calls::GET_VERSION => GetVersion::Args.method(:serialize),
|
|
64
|
+
Wire::Calls::GET_HEIGHT => GetHeight::Args.method(:serialize),
|
|
65
|
+
Wire::Calls::GET_HEADER_FOR_HEIGHT => GetHeaderForHeight::Args.method(:serialize),
|
|
66
|
+
Wire::Calls::IS_AUTHENTICATED => IsAuthenticated::Args.method(:serialize),
|
|
67
|
+
Wire::Calls::WAIT_FOR_AUTHENTICATION => WaitForAuthentication::Args.method(:serialize),
|
|
68
|
+
Wire::Calls::CREATE_ACTION => CreateActionArgs.method(:serialize),
|
|
69
|
+
Wire::Calls::SIGN_ACTION => SignActionArgs.method(:serialize),
|
|
70
|
+
Wire::Calls::ABORT_ACTION => AbortAction.method(:serialize_args),
|
|
71
|
+
Wire::Calls::INTERNALIZE_ACTION => InternalizeActionArgs.method(:serialize),
|
|
72
|
+
Wire::Calls::LIST_ACTIONS => ListActionsArgs.method(:serialize),
|
|
73
|
+
Wire::Calls::LIST_OUTPUTS => ListOutputs.method(:serialize_args),
|
|
74
|
+
Wire::Calls::RELINQUISH_OUTPUT => RelinquishOutput.method(:serialize_args),
|
|
75
|
+
Wire::Calls::ACQUIRE_CERTIFICATE => AcquireCertificate.method(:serialize_args),
|
|
76
|
+
Wire::Calls::LIST_CERTIFICATES => ListCertificates.method(:serialize_args),
|
|
77
|
+
Wire::Calls::PROVE_CERTIFICATE => ProveCertificate.method(:serialize_args),
|
|
78
|
+
Wire::Calls::RELINQUISH_CERTIFICATE => RelinquishCertificate.method(:serialize_args),
|
|
79
|
+
Wire::Calls::DISCOVER_BY_IDENTITY_KEY => DiscoverByIdentityKey.method(:serialize_args),
|
|
80
|
+
Wire::Calls::DISCOVER_BY_ATTRIBUTES => DiscoverByAttributes.method(:serialize_args)
|
|
81
|
+
}.freeze
|
|
82
|
+
|
|
83
|
+
# Client-side: deserialise incoming result payload for each call.
|
|
84
|
+
DESERIALIZE_RESULT = {
|
|
85
|
+
Wire::Calls::GET_PUBLIC_KEY => GetPublicKey::Result.method(:deserialize),
|
|
86
|
+
Wire::Calls::REVEAL_COUNTERPARTY_KEY_LINKAGE => RevealCounterpartyKeyLinkage::Result.method(:deserialize),
|
|
87
|
+
Wire::Calls::REVEAL_SPECIFIC_KEY_LINKAGE => RevealSpecificKeyLinkage::Result.method(:deserialize),
|
|
88
|
+
Wire::Calls::ENCRYPT => Encrypt::Result.method(:deserialize),
|
|
89
|
+
Wire::Calls::DECRYPT => Decrypt::Result.method(:deserialize),
|
|
90
|
+
Wire::Calls::CREATE_HMAC => CreateHmac::Result.method(:deserialize),
|
|
91
|
+
Wire::Calls::VERIFY_HMAC => VerifyHmac::Result.method(:deserialize),
|
|
92
|
+
Wire::Calls::CREATE_SIGNATURE => CreateSignature::Result.method(:deserialize),
|
|
93
|
+
Wire::Calls::VERIFY_SIGNATURE => VerifySignature::Result.method(:deserialize),
|
|
94
|
+
Wire::Calls::GET_NETWORK => GetNetwork::Result.method(:deserialize),
|
|
95
|
+
Wire::Calls::GET_VERSION => GetVersion::Result.method(:deserialize),
|
|
96
|
+
Wire::Calls::GET_HEIGHT => GetHeight::Result.method(:deserialize),
|
|
97
|
+
Wire::Calls::GET_HEADER_FOR_HEIGHT => GetHeaderForHeight::Result.method(:deserialize),
|
|
98
|
+
Wire::Calls::IS_AUTHENTICATED => IsAuthenticated::Result.method(:deserialize),
|
|
99
|
+
Wire::Calls::WAIT_FOR_AUTHENTICATION => WaitForAuthentication::Result.method(:deserialize),
|
|
100
|
+
Wire::Calls::CREATE_ACTION => CreateActionResult.method(:deserialize),
|
|
101
|
+
Wire::Calls::SIGN_ACTION => SignActionResult.method(:deserialize),
|
|
102
|
+
Wire::Calls::ABORT_ACTION => AbortAction.method(:deserialize_result),
|
|
103
|
+
Wire::Calls::INTERNALIZE_ACTION => InternalizeActionResult.method(:deserialize),
|
|
104
|
+
Wire::Calls::LIST_ACTIONS => ListActionsResult.method(:deserialize),
|
|
105
|
+
Wire::Calls::LIST_OUTPUTS => ListOutputs.method(:deserialize_result),
|
|
106
|
+
Wire::Calls::RELINQUISH_OUTPUT => RelinquishOutput.method(:deserialize_result),
|
|
107
|
+
Wire::Calls::ACQUIRE_CERTIFICATE => AcquireCertificate.method(:deserialize_result),
|
|
108
|
+
Wire::Calls::LIST_CERTIFICATES => ListCertificates.method(:deserialize_result),
|
|
109
|
+
Wire::Calls::PROVE_CERTIFICATE => ProveCertificate.method(:deserialize_result),
|
|
110
|
+
Wire::Calls::RELINQUISH_CERTIFICATE => RelinquishCertificate.method(:deserialize_result),
|
|
111
|
+
Wire::Calls::DISCOVER_BY_IDENTITY_KEY => DiscoverByIdentityKey.method(:deserialize_result),
|
|
112
|
+
Wire::Calls::DISCOVER_BY_ATTRIBUTES => DiscoverByAttributes.method(:deserialize_result)
|
|
113
|
+
}.freeze
|
|
114
|
+
|
|
115
|
+
# Server-side: deserialise incoming args payload for each call.
|
|
116
|
+
DESERIALIZE_ARGS = {
|
|
117
|
+
Wire::Calls::GET_PUBLIC_KEY => GetPublicKey::Args.method(:deserialize),
|
|
118
|
+
Wire::Calls::REVEAL_COUNTERPARTY_KEY_LINKAGE => RevealCounterpartyKeyLinkage::Args.method(:deserialize),
|
|
119
|
+
Wire::Calls::REVEAL_SPECIFIC_KEY_LINKAGE => RevealSpecificKeyLinkage::Args.method(:deserialize),
|
|
120
|
+
Wire::Calls::ENCRYPT => Encrypt::Args.method(:deserialize),
|
|
121
|
+
Wire::Calls::DECRYPT => Decrypt::Args.method(:deserialize),
|
|
122
|
+
Wire::Calls::CREATE_HMAC => CreateHmac::Args.method(:deserialize),
|
|
123
|
+
Wire::Calls::VERIFY_HMAC => VerifyHmac::Args.method(:deserialize),
|
|
124
|
+
Wire::Calls::CREATE_SIGNATURE => CreateSignature::Args.method(:deserialize),
|
|
125
|
+
Wire::Calls::VERIFY_SIGNATURE => VerifySignature::Args.method(:deserialize),
|
|
126
|
+
Wire::Calls::GET_NETWORK => GetNetwork::Args.method(:deserialize),
|
|
127
|
+
Wire::Calls::GET_VERSION => GetVersion::Args.method(:deserialize),
|
|
128
|
+
Wire::Calls::GET_HEIGHT => GetHeight::Args.method(:deserialize),
|
|
129
|
+
Wire::Calls::GET_HEADER_FOR_HEIGHT => GetHeaderForHeight::Args.method(:deserialize),
|
|
130
|
+
Wire::Calls::IS_AUTHENTICATED => IsAuthenticated::Args.method(:deserialize),
|
|
131
|
+
Wire::Calls::WAIT_FOR_AUTHENTICATION => WaitForAuthentication::Args.method(:deserialize),
|
|
132
|
+
Wire::Calls::CREATE_ACTION => CreateActionArgs.method(:deserialize),
|
|
133
|
+
Wire::Calls::SIGN_ACTION => SignActionArgs.method(:deserialize),
|
|
134
|
+
Wire::Calls::ABORT_ACTION => AbortAction.method(:deserialize_args),
|
|
135
|
+
Wire::Calls::INTERNALIZE_ACTION => InternalizeActionArgs.method(:deserialize),
|
|
136
|
+
Wire::Calls::LIST_ACTIONS => ListActionsArgs.method(:deserialize),
|
|
137
|
+
Wire::Calls::LIST_OUTPUTS => ListOutputs.method(:deserialize_args),
|
|
138
|
+
Wire::Calls::RELINQUISH_OUTPUT => RelinquishOutput.method(:deserialize_args),
|
|
139
|
+
Wire::Calls::ACQUIRE_CERTIFICATE => AcquireCertificate.method(:deserialize_args),
|
|
140
|
+
Wire::Calls::LIST_CERTIFICATES => ListCertificates.method(:deserialize_args),
|
|
141
|
+
Wire::Calls::PROVE_CERTIFICATE => ProveCertificate.method(:deserialize_args),
|
|
142
|
+
Wire::Calls::RELINQUISH_CERTIFICATE => RelinquishCertificate.method(:deserialize_args),
|
|
143
|
+
Wire::Calls::DISCOVER_BY_IDENTITY_KEY => DiscoverByIdentityKey.method(:deserialize_args),
|
|
144
|
+
Wire::Calls::DISCOVER_BY_ATTRIBUTES => DiscoverByAttributes.method(:deserialize_args)
|
|
145
|
+
}.freeze
|
|
146
|
+
|
|
147
|
+
# Server-side: serialise outgoing result for each call.
|
|
148
|
+
SERIALIZE_RESULT = {
|
|
149
|
+
Wire::Calls::GET_PUBLIC_KEY => GetPublicKey::Result.method(:serialize),
|
|
150
|
+
Wire::Calls::REVEAL_COUNTERPARTY_KEY_LINKAGE => RevealCounterpartyKeyLinkage::Result.method(:serialize),
|
|
151
|
+
Wire::Calls::REVEAL_SPECIFIC_KEY_LINKAGE => RevealSpecificKeyLinkage::Result.method(:serialize),
|
|
152
|
+
Wire::Calls::ENCRYPT => Encrypt::Result.method(:serialize),
|
|
153
|
+
Wire::Calls::DECRYPT => Decrypt::Result.method(:serialize),
|
|
154
|
+
Wire::Calls::CREATE_HMAC => CreateHmac::Result.method(:serialize),
|
|
155
|
+
Wire::Calls::VERIFY_HMAC => VerifyHmac::Result.method(:serialize),
|
|
156
|
+
Wire::Calls::CREATE_SIGNATURE => CreateSignature::Result.method(:serialize),
|
|
157
|
+
Wire::Calls::VERIFY_SIGNATURE => VerifySignature::Result.method(:serialize),
|
|
158
|
+
Wire::Calls::GET_NETWORK => GetNetwork::Result.method(:serialize),
|
|
159
|
+
Wire::Calls::GET_VERSION => GetVersion::Result.method(:serialize),
|
|
160
|
+
Wire::Calls::GET_HEIGHT => GetHeight::Result.method(:serialize),
|
|
161
|
+
Wire::Calls::GET_HEADER_FOR_HEIGHT => GetHeaderForHeight::Result.method(:serialize),
|
|
162
|
+
Wire::Calls::IS_AUTHENTICATED => IsAuthenticated::Result.method(:serialize),
|
|
163
|
+
Wire::Calls::WAIT_FOR_AUTHENTICATION => WaitForAuthentication::Result.method(:serialize),
|
|
164
|
+
Wire::Calls::CREATE_ACTION => CreateActionResult.method(:serialize),
|
|
165
|
+
Wire::Calls::SIGN_ACTION => SignActionResult.method(:serialize),
|
|
166
|
+
Wire::Calls::ABORT_ACTION => AbortAction.method(:serialize_result),
|
|
167
|
+
Wire::Calls::INTERNALIZE_ACTION => InternalizeActionResult.method(:serialize),
|
|
168
|
+
Wire::Calls::LIST_ACTIONS => ListActionsResult.method(:serialize),
|
|
169
|
+
Wire::Calls::LIST_OUTPUTS => ListOutputs.method(:serialize_result),
|
|
170
|
+
Wire::Calls::RELINQUISH_OUTPUT => RelinquishOutput.method(:serialize_result),
|
|
171
|
+
Wire::Calls::ACQUIRE_CERTIFICATE => AcquireCertificate.method(:serialize_result),
|
|
172
|
+
Wire::Calls::LIST_CERTIFICATES => ListCertificates.method(:serialize_result),
|
|
173
|
+
Wire::Calls::PROVE_CERTIFICATE => ProveCertificate.method(:serialize_result),
|
|
174
|
+
Wire::Calls::RELINQUISH_CERTIFICATE => RelinquishCertificate.method(:serialize_result),
|
|
175
|
+
Wire::Calls::DISCOVER_BY_IDENTITY_KEY => DiscoverByIdentityKey.method(:serialize_result),
|
|
176
|
+
Wire::Calls::DISCOVER_BY_ATTRIBUTES => DiscoverByAttributes.method(:serialize_result)
|
|
177
|
+
}.freeze
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'uri'
|
|
6
|
+
|
|
7
|
+
module BSV
|
|
8
|
+
module Wallet
|
|
9
|
+
module Substrates
|
|
10
|
+
# JSON-RPC-style HTTP substrate implementing BRC-100.
|
|
11
|
+
#
|
|
12
|
+
# Dispatches all 28 BRC-100 methods as JSON POST requests to
|
|
13
|
+
# {base_url}/v1/wallet/{methodNameInCamelCase}. Request bodies are
|
|
14
|
+
# deep-converted from snake_case to camelCase via {BSV::WireFormat.to_wire};
|
|
15
|
+
# responses are deep-converted back via {BSV::WireFormat.from_wire}.
|
|
16
|
+
#
|
|
17
|
+
# This substrate does NOT use the BRC-103 binary frame codec — it speaks
|
|
18
|
+
# plain JSON over HTTP, matching the Go SDK HTTPWalletJSON implementation.
|
|
19
|
+
#
|
|
20
|
+
# @example
|
|
21
|
+
# client = BSV::Wallet::Substrates::HTTPWalletJSON.new(
|
|
22
|
+
# base_url: 'https://wallet.example.com',
|
|
23
|
+
# headers: { 'Authorization' => 'Bearer token' }
|
|
24
|
+
# )
|
|
25
|
+
# client.get_network # => { network: 'mainnet' }
|
|
26
|
+
class HTTPWalletJSON
|
|
27
|
+
include Interface::BRC100
|
|
28
|
+
|
|
29
|
+
# Maps each BRC-100 Ruby method name to its camelCase wire name.
|
|
30
|
+
# authenticated? maps to isAuthenticated — the BRC-100 wire name uses the
|
|
31
|
+
# is_ prefix convention; the Ruby predicate suffix is dropped for the lookup.
|
|
32
|
+
WIRE_METHOD_NAMES = Wire::Calls::CALL_TO_METHOD.each_with_object({}) do |(call_byte, ruby_method), map|
|
|
33
|
+
snake = call_byte == Wire::Calls::IS_AUTHENTICATED ? 'is_authenticated' : ruby_method.to_s
|
|
34
|
+
map[ruby_method] = BSV::WireFormat.snake_to_camel(snake)
|
|
35
|
+
end.freeze
|
|
36
|
+
|
|
37
|
+
# @param base_url [String] wallet base URL (e.g. 'https://wallet.example')
|
|
38
|
+
# @param http_client [#request, nil] injectable HTTP client for testing;
|
|
39
|
+
# must respond to +#request(uri, net_http_request)+. Defaults to +Net::HTTP+.
|
|
40
|
+
# @param headers [Hash] additional headers merged into every request
|
|
41
|
+
def initialize(base_url:, http_client: nil, headers: {})
|
|
42
|
+
@base_url = base_url.to_s.chomp('/')
|
|
43
|
+
@http_client = http_client
|
|
44
|
+
@headers = headers.transform_keys(&:to_s)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
Wire::Calls::CALL_TO_METHOD.each_value do |method_name|
|
|
48
|
+
define_method(method_name) do |**args|
|
|
49
|
+
_dispatch(method_name, args)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def _dispatch(method_name, args)
|
|
56
|
+
wire_name = WIRE_METHOD_NAMES.fetch(method_name)
|
|
57
|
+
url = URI.parse("#{@base_url}/v1/wallet/#{wire_name}")
|
|
58
|
+
body = args.empty? ? {} : BSV::WireFormat.to_wire(args)
|
|
59
|
+
|
|
60
|
+
response = _post(url, body)
|
|
61
|
+
_handle_response(response)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def _post(url, body)
|
|
65
|
+
req = Net::HTTP::Post.new(url)
|
|
66
|
+
@headers.each { |k, v| req[k] = v }
|
|
67
|
+
req['Content-Type'] = 'application/json'
|
|
68
|
+
req['Accept'] = 'application/json'
|
|
69
|
+
req.body = body.to_json
|
|
70
|
+
|
|
71
|
+
_execute_request(url, req)
|
|
72
|
+
rescue BSV::Wallet::Error
|
|
73
|
+
raise
|
|
74
|
+
rescue StandardError => e
|
|
75
|
+
raise BSV::Wallet::Error.new("HTTP request failed: #{e.message}", code: 1)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def _execute_request(url, req)
|
|
79
|
+
if @http_client
|
|
80
|
+
@http_client.request(url, req)
|
|
81
|
+
else
|
|
82
|
+
Net::HTTP.start(url.host, url.port,
|
|
83
|
+
use_ssl: url.scheme == 'https') { |conn| conn.request(req) }
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def _handle_response(response)
|
|
88
|
+
status = response.code.to_i
|
|
89
|
+
raw = response.body.to_s
|
|
90
|
+
|
|
91
|
+
if (200..299).cover?(status)
|
|
92
|
+
_parse_success(raw, status)
|
|
93
|
+
else
|
|
94
|
+
_raise_error(raw)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def _parse_success(raw, status)
|
|
99
|
+
return {} if status == 204 || raw.empty?
|
|
100
|
+
|
|
101
|
+
begin
|
|
102
|
+
parsed = JSON.parse(raw)
|
|
103
|
+
rescue JSON::ParserError => e
|
|
104
|
+
raise BSV::Wallet::Error.new("Invalid JSON in response: #{e.message}", code: 1)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
return parsed unless parsed.is_a?(Hash)
|
|
108
|
+
|
|
109
|
+
BSV::WireFormat.from_wire(parsed)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def _raise_error(raw)
|
|
113
|
+
error_hash = begin
|
|
114
|
+
JSON.parse(raw)
|
|
115
|
+
rescue JSON::ParserError
|
|
116
|
+
{}
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
code = error_hash['code'].to_i
|
|
120
|
+
message = error_hash['message'].to_s
|
|
121
|
+
stack = error_hash['stack'].to_s
|
|
122
|
+
code = 1 if code.zero?
|
|
123
|
+
|
|
124
|
+
raise BSV::Wallet.error_from_wire(code, message.empty? ? raw : message, stack)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'uri'
|
|
5
|
+
|
|
6
|
+
module BSV
|
|
7
|
+
module Wallet
|
|
8
|
+
module Substrates
|
|
9
|
+
# Concrete {WalletWire} implementation over HTTP/HTTPS.
|
|
10
|
+
#
|
|
11
|
+
# Transmits binary BRC-103 request frames via HTTP POST to `{base_url}/wallet`
|
|
12
|
+
# using `Content-Type: application/octet-stream`, and returns the raw binary
|
|
13
|
+
# response body.
|
|
14
|
+
#
|
|
15
|
+
# The optional `http_client:` parameter accepts any object responding to
|
|
16
|
+
# `#request(uri, net_http_request)` — matching the injectable client
|
|
17
|
+
# convention used throughout this SDK. When omitted, `Net::HTTP` is used
|
|
18
|
+
# directly.
|
|
19
|
+
#
|
|
20
|
+
# @example Direct wire usage
|
|
21
|
+
# wire = BSV::Wallet::Substrates::HTTPWalletWire.new(base_url: 'https://wallet.example')
|
|
22
|
+
# client = BSV::Wallet::WalletWireTransceiver.new(wire)
|
|
23
|
+
# client.get_network #=> { network: :mainnet }
|
|
24
|
+
#
|
|
25
|
+
# @example Convenience factory
|
|
26
|
+
# client = BSV::Wallet::Substrates::HTTPWalletWire.client(base_url: 'https://wallet.example')
|
|
27
|
+
# client.get_network #=> { network: :mainnet }
|
|
28
|
+
class HTTPWalletWire
|
|
29
|
+
include WalletWire
|
|
30
|
+
|
|
31
|
+
# @param base_url [String] wallet base URL (e.g. 'https://wallet.example')
|
|
32
|
+
# @param http_client [#request, nil] injectable HTTP client for testing;
|
|
33
|
+
# must respond to +#request(uri, net_http_request)+. Defaults to +Net::HTTP+.
|
|
34
|
+
# @param headers [Hash] additional headers merged into every request
|
|
35
|
+
def initialize(base_url:, http_client: nil, headers: {})
|
|
36
|
+
@uri = build_uri(base_url)
|
|
37
|
+
@http_client = http_client
|
|
38
|
+
@headers = headers.transform_keys(&:to_s)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Convenience factory: wraps a new {HTTPWalletWire} in a {WalletWireTransceiver}.
|
|
42
|
+
#
|
|
43
|
+
# @param base_url [String]
|
|
44
|
+
# @param http_client [#request, nil]
|
|
45
|
+
# @param headers [Hash]
|
|
46
|
+
# @return [WalletWireTransceiver]
|
|
47
|
+
def self.client(base_url:, http_client: nil, headers: {})
|
|
48
|
+
WalletWireTransceiver.new(new(base_url: base_url, http_client: http_client, headers: headers))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# POST binary frame to `{base_url}/wallet` and return the binary response body.
|
|
52
|
+
#
|
|
53
|
+
# @param message [String] binary request frame (ASCII-8BIT)
|
|
54
|
+
# @return [String] binary result frame (ASCII-8BIT)
|
|
55
|
+
# @raise [BSV::Wallet::Error] on non-2xx HTTP status or network failure
|
|
56
|
+
def transmit_to_wallet(message)
|
|
57
|
+
http_post(message)
|
|
58
|
+
rescue BSV::Wallet::Error
|
|
59
|
+
raise
|
|
60
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
|
|
61
|
+
Net::OpenTimeout, Net::ReadTimeout, Net::HTTPError => e
|
|
62
|
+
raise BSV::Wallet::Error.new("wallet connection failed: #{e.message}", code: 1)
|
|
63
|
+
rescue StandardError => e
|
|
64
|
+
raise BSV::Wallet::Error.new("wallet request failed: #{e.message}", code: 1)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def build_uri(base_url)
|
|
70
|
+
normalised = base_url.to_s.chomp('/')
|
|
71
|
+
URI.parse("#{normalised}/wallet")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def http_post(body)
|
|
75
|
+
request = Net::HTTP::Post.new(@uri.path)
|
|
76
|
+
@headers.each { |k, v| request[k] = v }
|
|
77
|
+
request['Content-Type'] = 'application/octet-stream'
|
|
78
|
+
request.body = body.respond_to?(:b) ? body.b : body.pack('C*')
|
|
79
|
+
|
|
80
|
+
response = execute_request(request)
|
|
81
|
+
|
|
82
|
+
raise BSV::Wallet::Error.new("HTTP #{response.code}: #{response.body.to_s.strip}", code: 1) unless response.is_a?(Net::HTTPSuccess)
|
|
83
|
+
|
|
84
|
+
(response.body || '').b
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def execute_request(request)
|
|
88
|
+
if @http_client
|
|
89
|
+
@http_client.request(@uri, request)
|
|
90
|
+
else
|
|
91
|
+
Net::HTTP.start(@uri.host, @uri.port, use_ssl: @uri.scheme == 'https') do |http|
|
|
92
|
+
http.request(request)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BSV
|
|
4
|
+
module Wallet
|
|
5
|
+
# Abstract binary transport for BRC-103 wallet communication.
|
|
6
|
+
#
|
|
7
|
+
# Include this module and implement {#transmit_to_wallet} to provide a
|
|
8
|
+
# concrete transport (e.g. HTTP, in-process loopback, Unix socket).
|
|
9
|
+
module WalletWire
|
|
10
|
+
# Transmit a binary request frame to the wallet and return the binary result frame.
|
|
11
|
+
#
|
|
12
|
+
# @param message [String] binary request frame (ASCII-8BIT)
|
|
13
|
+
# @return [String] binary result frame (ASCII-8BIT)
|
|
14
|
+
# @raise [NotImplementedError] unless overridden by the including class
|
|
15
|
+
def transmit_to_wallet(message)
|
|
16
|
+
raise NotImplementedError, "#{self.class}#transmit_to_wallet is not implemented"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BSV
|
|
4
|
+
module Wallet
|
|
5
|
+
# Server-side BRC-103 dispatcher.
|
|
6
|
+
#
|
|
7
|
+
# Takes any {Interface::BRC100} implementation and exposes it as a
|
|
8
|
+
# {WalletWire}. Decodes incoming binary request frames, dispatches to the
|
|
9
|
+
# wallet, serialises the result, and returns a binary result frame.
|
|
10
|
+
#
|
|
11
|
+
# Error boundary: any {Error} from the wallet is serialised into an error
|
|
12
|
+
# frame so the client can rehydrate it. Any other {StandardError} is wrapped
|
|
13
|
+
# in {Error} (code 1) before framing — the processor never lets a Ruby
|
|
14
|
+
# exception propagate past this boundary.
|
|
15
|
+
#
|
|
16
|
+
# @example Wrap a ProtoWallet for loopback testing
|
|
17
|
+
# processor = BSV::Wallet::WalletWireProcessor.new(proto_wallet)
|
|
18
|
+
# transceiver = BSV::Wallet::WalletWireTransceiver.new(processor)
|
|
19
|
+
class WalletWireProcessor
|
|
20
|
+
include WalletWire
|
|
21
|
+
|
|
22
|
+
# @param wallet [Interface::BRC100] any BRC-100 wallet implementation
|
|
23
|
+
def initialize(wallet)
|
|
24
|
+
@wallet = wallet
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Process a binary request frame and return a binary result frame.
|
|
28
|
+
#
|
|
29
|
+
# @param request_bytes [String] binary request frame
|
|
30
|
+
# @return [String] binary result frame (success or error)
|
|
31
|
+
def transmit_to_wallet(request_bytes)
|
|
32
|
+
req = Wire::Frame.read_request(request_bytes)
|
|
33
|
+
call_byte = req[:call]
|
|
34
|
+
|
|
35
|
+
method_name = Wire::Calls::CALL_TO_METHOD.fetch(call_byte) do
|
|
36
|
+
raise Error.new("unknown call byte: #{call_byte}", code: 1)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
serialize_result = Serializer::SERIALIZE_RESULT.fetch(call_byte) do
|
|
40
|
+
raise Error.new("no result serialiser for call #{call_byte}", code: 1)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
args = Serializer::DESERIALIZE_ARGS.fetch(call_byte) do
|
|
44
|
+
raise Error.new("no args deserialiser for call #{call_byte}", code: 1)
|
|
45
|
+
end.call(req[:params])
|
|
46
|
+
|
|
47
|
+
args[:originator] = req[:originator] unless req[:originator].empty?
|
|
48
|
+
|
|
49
|
+
result = @wallet.public_send(method_name, **args)
|
|
50
|
+
payload = serialize_result.call(result)
|
|
51
|
+
Wire::Frame.write_result(payload: payload)
|
|
52
|
+
rescue NotImplementedError => e
|
|
53
|
+
Wire::Frame.write_error(error: UnsupportedActionError.new(e.message.to_s))
|
|
54
|
+
rescue Error => e
|
|
55
|
+
Wire::Frame.write_error(error: e)
|
|
56
|
+
rescue StandardError => e
|
|
57
|
+
Wire::Frame.write_error(error: Error.new(e.message.to_s, code: 1))
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|