bsv-sdk 0.15.0 → 0.16.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 +13 -0
- data/lib/bsv/auth/auth_middleware.rb +6 -6
- data/lib/bsv/auth/certificate.rb +16 -16
- data/lib/bsv/auth/master_certificate.rb +5 -5
- data/lib/bsv/auth/nonce.rb +13 -13
- data/lib/bsv/auth/peer.rb +53 -53
- data/lib/bsv/auth/verifiable_certificate.rb +1 -1
- data/lib/bsv/identity/client.rb +26 -32
- data/lib/bsv/mcp/tools/broadcast_p2pkh.rb +17 -11
- data/lib/bsv/mcp/tools/check_balance.rb +16 -4
- data/lib/bsv/mcp/tools/fetch_tx.rb +11 -4
- data/lib/bsv/mcp/tools/fetch_utxos.rb +16 -4
- data/lib/bsv/network/arc.rb +13 -153
- data/lib/bsv/network/whats_on_chain.rb +13 -107
- data/lib/bsv/overlay/admin_token_template.rb +4 -4
- data/lib/bsv/registry/client.rb +23 -27
- data/lib/bsv/script/push_drop_template.rb +4 -4
- data/lib/bsv/version.rb +1 -1
- data/lib/bsv/wallet/errors.rb +47 -0
- data/lib/bsv/wallet/interface/brc100.rb +267 -0
- data/lib/bsv/wallet/interface.rb +9 -0
- data/lib/bsv/wallet/proto_wallet/key_deriver.rb +150 -0
- data/lib/bsv/wallet/proto_wallet/validators.rb +74 -0
- data/lib/bsv/wallet/proto_wallet.rb +321 -0
- data/lib/bsv/wallet.rb +16 -0
- data/lib/bsv-sdk.rb +4 -1
- metadata +22 -1
data/lib/bsv/network/arc.rb
CHANGED
|
@@ -2,164 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
module BSV
|
|
4
4
|
module Network
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# the protocol into +BroadcastResponse+ instances or raised +BroadcastError+
|
|
10
|
-
# exceptions as required by consumer code.
|
|
11
|
-
#
|
|
12
|
-
# Any object responding to #broadcast(tx) can serve as a broadcaster;
|
|
13
|
-
# this class implements that contract using the ARC API.
|
|
5
|
+
# @deprecated Use {BSV::Network::Protocols::ARC} directly instead.
|
|
6
|
+
# The facade converted clean Result objects into exceptions — every
|
|
7
|
+
# consumer immediately caught them and converted back to data.
|
|
8
|
+
# Use the protocol layer, which returns Result objects natively.
|
|
14
9
|
class ARC
|
|
15
|
-
#
|
|
16
|
-
|
|
17
|
-
# @param testnet [Boolean] when true, uses the GorillaPool testnet endpoint
|
|
18
|
-
# @param api_key [String, nil] optional bearer token for Authorization
|
|
19
|
-
# @param http_client [#request, nil] injectable HTTP client for testing
|
|
20
|
-
# @param opts [Hash] ARC-specific options forwarded to the protocol
|
|
21
|
-
# (e.g. +deployment_id:+, +callback_url:+, +callback_token:+)
|
|
22
|
-
# @return [ARC]
|
|
23
|
-
def self.default(testnet: false, api_key: nil, http_client: nil, **opts)
|
|
24
|
-
provider = Providers::GorillaPool.default(testnet: testnet)
|
|
25
|
-
arc_protocol = provider.protocol_for(:broadcast)
|
|
26
|
-
base_url = arc_protocol.base_url
|
|
27
|
-
new(
|
|
28
|
-
base_url,
|
|
29
|
-
api_key: api_key,
|
|
30
|
-
http_client: http_client,
|
|
31
|
-
**opts
|
|
32
|
-
)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# ARC response statuses that indicate the transaction was NOT accepted.
|
|
36
|
-
REJECTED_STATUSES = %w[
|
|
37
|
-
REJECTED
|
|
38
|
-
DOUBLE_SPEND_ATTEMPTED
|
|
39
|
-
INVALID
|
|
40
|
-
MALFORMED
|
|
41
|
-
MINED_IN_STALE_BLOCK
|
|
42
|
-
].freeze
|
|
43
|
-
|
|
44
|
-
# @param url_or_protocol [String, Protocols::ARC] ARC base URL (without
|
|
45
|
-
# trailing slash) or a pre-configured +Protocols::ARC+ instance. When a
|
|
46
|
-
# URL string is supplied, the remaining keyword arguments are forwarded to
|
|
47
|
-
# the underlying protocol constructor. When a protocol instance is supplied,
|
|
48
|
-
# all keyword arguments are ignored.
|
|
49
|
-
# @param api_key [String, nil] optional bearer token for Authorization
|
|
50
|
-
# @param deployment_id [String, nil] optional deployment identifier for
|
|
51
|
-
# the +XDeployment-ID+ header; defaults to a per-instance random value
|
|
52
|
-
# @param callback_url [String, nil] optional +X-CallbackUrl+ for ARC
|
|
53
|
-
# status callbacks
|
|
54
|
-
# @param callback_token [String, nil] optional +X-CallbackToken+ for
|
|
55
|
-
# ARC status callback authentication
|
|
56
|
-
# @param http_client [#request, nil] injectable HTTP client for testing
|
|
57
|
-
def initialize(url_or_protocol, api_key: nil, deployment_id: nil, callback_url: nil,
|
|
58
|
-
callback_token: nil, http_client: nil)
|
|
59
|
-
@protocol =
|
|
60
|
-
if url_or_protocol.is_a?(String)
|
|
61
|
-
Protocols::ARC.new(
|
|
62
|
-
base_url: url_or_protocol,
|
|
63
|
-
api_key: api_key,
|
|
64
|
-
deployment_id: deployment_id,
|
|
65
|
-
callback_url: callback_url,
|
|
66
|
-
callback_token: callback_token,
|
|
67
|
-
http_client: http_client
|
|
68
|
-
)
|
|
69
|
-
else
|
|
70
|
-
url_or_protocol
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Submit a transaction to ARC.
|
|
75
|
-
#
|
|
76
|
-
# @param tx [Transaction] the transaction to broadcast
|
|
77
|
-
# @param wait_for [String, nil] ARC wait condition
|
|
78
|
-
# @param skip_fee_validation [Boolean, nil] when truthy, sends X-SkipFeeValidation header
|
|
79
|
-
# @param skip_script_validation [Boolean, nil] when truthy, sends X-SkipScriptValidation header
|
|
80
|
-
# @return [BroadcastResponse]
|
|
81
|
-
# @raise [BroadcastError] when ARC returns a non-2xx HTTP status or a
|
|
82
|
-
# rejected/orphan +txStatus+
|
|
83
|
-
def broadcast(tx, wait_for: nil, skip_fee_validation: nil, skip_script_validation: nil)
|
|
84
|
-
result = @protocol.call(
|
|
85
|
-
:broadcast, tx,
|
|
86
|
-
wait_for: wait_for,
|
|
87
|
-
skip_fee_validation: skip_fee_validation,
|
|
88
|
-
skip_script_validation: skip_script_validation
|
|
89
|
-
)
|
|
90
|
-
result_to_response!(result)
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Submit multiple transactions to ARC in a single batch request.
|
|
94
|
-
#
|
|
95
|
-
# Returns a mixed array of {BroadcastResponse} and {BroadcastError} objects.
|
|
96
|
-
# Per-transaction rejections are returned as {BroadcastError} values rather
|
|
97
|
-
# than raised. Only HTTP-level errors raise a {BroadcastError} for the whole batch.
|
|
98
|
-
#
|
|
99
|
-
# @param txs [Array<Transaction>] transactions to broadcast
|
|
100
|
-
# @param wait_for [String, nil] ARC wait condition
|
|
101
|
-
# @param skip_fee_validation [Boolean, nil]
|
|
102
|
-
# @param skip_script_validation [Boolean, nil]
|
|
103
|
-
# @return [Array<BroadcastResponse, BroadcastError>]
|
|
104
|
-
# @raise [BroadcastError] when ARC returns a non-2xx HTTP status
|
|
105
|
-
def broadcast_many(txs, wait_for: nil, skip_fee_validation: nil, skip_script_validation: nil)
|
|
106
|
-
result = @protocol.call(
|
|
107
|
-
:broadcast_many, txs,
|
|
108
|
-
wait_for: wait_for,
|
|
109
|
-
skip_fee_validation: skip_fee_validation,
|
|
110
|
-
skip_script_validation: skip_script_validation
|
|
111
|
-
)
|
|
10
|
+
# Raised when deprecated facade classes are instantiated.
|
|
11
|
+
class DeprecationError < StandardError; end
|
|
112
12
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
else
|
|
117
|
-
raise broadcast_error_from_result(result)
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# Query the status of a previously submitted transaction.
|
|
122
|
-
#
|
|
123
|
-
# @param txid [String] transaction ID to query
|
|
124
|
-
# @return [BroadcastResponse]
|
|
125
|
-
# @raise [BroadcastError] on failure
|
|
126
|
-
def status(txid)
|
|
127
|
-
result = @protocol.call(:get_tx_status, txid)
|
|
128
|
-
result_to_response!(result)
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
private
|
|
132
|
-
|
|
133
|
-
# Translate a single-tx Result into a BroadcastResponse or raise BroadcastError.
|
|
134
|
-
def result_to_response!(result)
|
|
135
|
-
case result
|
|
136
|
-
when Result::Success
|
|
137
|
-
BroadcastResponse.new(result.data)
|
|
138
|
-
else
|
|
139
|
-
raise broadcast_error_from_result(result)
|
|
140
|
-
end
|
|
141
|
-
end
|
|
13
|
+
MESSAGE = 'BSV::Network::ARC is deprecated. ' \
|
|
14
|
+
'Use BSV::Network::Protocols::ARC directly — it returns Result objects ' \
|
|
15
|
+
'instead of raising exceptions. See BSV::Network::Protocols::ARC for usage.'
|
|
142
16
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def item_to_response_or_error(item)
|
|
146
|
-
case item
|
|
147
|
-
when Result::Success
|
|
148
|
-
BroadcastResponse.new(item.data)
|
|
149
|
-
else
|
|
150
|
-
broadcast_error_from_result(item)
|
|
151
|
-
end
|
|
17
|
+
def self.default(**)
|
|
18
|
+
raise DeprecationError, MESSAGE
|
|
152
19
|
end
|
|
153
20
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
meta = result.metadata || {}
|
|
157
|
-
BroadcastError.new(
|
|
158
|
-
result.message,
|
|
159
|
-
status_code: meta[:status_code],
|
|
160
|
-
txid: meta[:txid],
|
|
161
|
-
arc_status: meta[:arc_status]
|
|
162
|
-
)
|
|
21
|
+
def initialize(*)
|
|
22
|
+
raise DeprecationError, MESSAGE
|
|
163
23
|
end
|
|
164
24
|
end
|
|
165
25
|
end
|
|
@@ -2,118 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
module BSV
|
|
4
4
|
module Network
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# #fetch_transaction(txid), #current_height,
|
|
10
|
-
# #get_block_header(height), and optionally
|
|
11
|
-
# #valid_root_for_height?(root_hex, height) can serve as a chain
|
|
12
|
-
# data source;
|
|
13
|
-
# this class implements that contract by delegating to
|
|
14
|
-
# Protocols::WoCREST.
|
|
15
|
-
#
|
|
16
|
-
# The HTTP client is injectable for testability. It must respond to
|
|
17
|
-
# #request(uri, request) and return an object with #code and #body.
|
|
5
|
+
# @deprecated Use {BSV::Network::Protocols::WoCREST} directly instead.
|
|
6
|
+
# The facade converted clean Result objects into exceptions — every
|
|
7
|
+
# consumer immediately caught them and converted back to data.
|
|
8
|
+
# Use the protocol layer, which returns Result objects natively.
|
|
18
9
|
class WhatsOnChain
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
# @param testnet [Boolean] when true, uses the testnet endpoint
|
|
22
|
-
# @param opts [Hash] forwarded to the underlying protocol (e.g. +api_key:+, +http_client:+)
|
|
23
|
-
# @return [WhatsOnChain]
|
|
24
|
-
def self.default(testnet: false, **opts)
|
|
25
|
-
provider = Providers::WhatsOnChain.default(testnet: testnet, **opts)
|
|
26
|
-
new(protocol: provider.protocol_for(:get_tx))
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# @param network [Symbol] :main, :mainnet, :test, :testnet, :stn (legacy compat)
|
|
30
|
-
# @param http_client [#request, nil] injectable HTTP client
|
|
31
|
-
# @param protocol [BSV::Network::Protocols::WoCREST, nil] pre-configured protocol
|
|
32
|
-
def initialize(network: :mainnet, http_client: nil, protocol: nil)
|
|
33
|
-
if protocol
|
|
34
|
-
@protocol = protocol
|
|
35
|
-
else
|
|
36
|
-
provider = Providers::WhatsOnChain.default(network: network, http_client: http_client)
|
|
37
|
-
@protocol = provider.protocol_for(:get_tx)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Fetch unspent transaction outputs for an address.
|
|
42
|
-
# @param address [String] BSV address
|
|
43
|
-
# @return [Array<UTXO>]
|
|
44
|
-
def fetch_utxos(address)
|
|
45
|
-
result = @protocol.call(:get_utxos_all, address)
|
|
46
|
-
raise_on_error(result)
|
|
47
|
-
|
|
48
|
-
result.data.map do |entry|
|
|
49
|
-
UTXO.new(
|
|
50
|
-
tx_hash: entry[:tx_hash],
|
|
51
|
-
tx_pos: entry[:tx_pos],
|
|
52
|
-
satoshis: entry[:satoshis],
|
|
53
|
-
height: entry[:height]
|
|
54
|
-
)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Fetch a raw transaction by its txid and parse it.
|
|
59
|
-
# @param txid [String] transaction ID (hex)
|
|
60
|
-
# @return [BSV::Transaction::Transaction]
|
|
61
|
-
def fetch_transaction(txid)
|
|
62
|
-
result = @protocol.call(:get_tx, txid)
|
|
63
|
-
raise_on_error(result)
|
|
64
|
-
|
|
65
|
-
BSV::Transaction::Transaction.from_hex(result.data)
|
|
66
|
-
end
|
|
10
|
+
# Raised when deprecated facade classes are instantiated.
|
|
11
|
+
class DeprecationError < StandardError; end
|
|
67
12
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def current_height
|
|
72
|
-
result = @protocol.call(:current_height)
|
|
73
|
-
raise_on_error(result)
|
|
13
|
+
MESSAGE = 'BSV::Network::WhatsOnChain is deprecated. ' \
|
|
14
|
+
'Use BSV::Network::Protocols::WoCREST directly — it returns Result objects ' \
|
|
15
|
+
'instead of raising exceptions. See BSV::Network::Protocols::WoCREST for usage.'
|
|
74
16
|
|
|
75
|
-
|
|
17
|
+
def self.default(**)
|
|
18
|
+
raise DeprecationError, MESSAGE
|
|
76
19
|
end
|
|
77
20
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
# @return [Hash] parsed block header JSON
|
|
81
|
-
# @raise [BSV::Network::ChainProviderError] on network or API error
|
|
82
|
-
def get_block_header(height)
|
|
83
|
-
result = @protocol.call(:get_block_header, height)
|
|
84
|
-
raise_on_error(result)
|
|
85
|
-
|
|
86
|
-
result.data
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# Verify that a merkle root is valid for the given block height.
|
|
90
|
-
# Returns +false+ when the block is not found (404); raises on other errors.
|
|
91
|
-
# @param root [String] expected merkle root as hex
|
|
92
|
-
# @param height [Integer] block height
|
|
93
|
-
# @return [Boolean]
|
|
94
|
-
# @raise [BSV::Network::ChainProviderError] on network or non-404 API error
|
|
95
|
-
def valid_root_for_height?(root, height)
|
|
96
|
-
result = @protocol.call(:valid_root, root, height)
|
|
97
|
-
return false if result.not_found?
|
|
98
|
-
|
|
99
|
-
raise_on_error(result)
|
|
100
|
-
|
|
101
|
-
result.data == true
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
private
|
|
105
|
-
|
|
106
|
-
# Translates a non-success Protocol result into a raised ChainProviderError.
|
|
107
|
-
#
|
|
108
|
-
# @param result [Result::Error, Result::NotFound]
|
|
109
|
-
# @raise [ChainProviderError]
|
|
110
|
-
def raise_on_error(result)
|
|
111
|
-
return if result.success?
|
|
112
|
-
|
|
113
|
-
raise ChainProviderError.new(
|
|
114
|
-
result.message || 'Request failed',
|
|
115
|
-
status_code: result.metadata[:status_code]
|
|
116
|
-
)
|
|
21
|
+
def initialize(*)
|
|
22
|
+
raise DeprecationError, MESSAGE
|
|
117
23
|
end
|
|
118
24
|
end
|
|
119
25
|
end
|
|
@@ -90,7 +90,7 @@ module BSV
|
|
|
90
90
|
|
|
91
91
|
sig_args = { hash_to_directly_sign: hash_bytes, protocol_id: @protocol_id, key_id: '1', counterparty: 'self' }
|
|
92
92
|
sig_args[:originator] = @originator if @originator
|
|
93
|
-
result = @wallet.create_signature(sig_args)
|
|
93
|
+
result = @wallet.create_signature(**sig_args)
|
|
94
94
|
|
|
95
95
|
sig_bytes = result[:signature].pack('C*')
|
|
96
96
|
sig_with_hashtype = sig_bytes + [sighash_type].pack('C')
|
|
@@ -171,14 +171,14 @@ module BSV
|
|
|
171
171
|
# Fetch the wallet's identity key (compressed public key hex)
|
|
172
172
|
id_args = { identity_key: true }
|
|
173
173
|
id_args[:originator] = @originator if @originator
|
|
174
|
-
identity_result = @wallet.get_public_key(id_args)
|
|
174
|
+
identity_result = @wallet.get_public_key(**id_args)
|
|
175
175
|
identity_key_hex = identity_result[:public_key]
|
|
176
176
|
identity_key_bytes = [identity_key_hex].pack('H*')
|
|
177
177
|
|
|
178
178
|
# Derive the locking public key for this protocol
|
|
179
179
|
lock_args = { protocol_id: protocol_id, key_id: '1', counterparty: 'self' }
|
|
180
180
|
lock_args[:originator] = @originator if @originator
|
|
181
|
-
locking_result = @wallet.get_public_key(lock_args)
|
|
181
|
+
locking_result = @wallet.get_public_key(**lock_args)
|
|
182
182
|
locking_pubkey_hex = locking_result[:public_key]
|
|
183
183
|
locking_pubkey_bytes = [locking_pubkey_hex].pack('H*')
|
|
184
184
|
|
|
@@ -192,7 +192,7 @@ module BSV
|
|
|
192
192
|
data_to_sign = (field_protocol + field_identity + field_domain + field_topic).unpack('C*')
|
|
193
193
|
sig_args = { data: data_to_sign, protocol_id: protocol_id, key_id: '1', counterparty: 'self' }
|
|
194
194
|
sig_args[:originator] = @originator if @originator
|
|
195
|
-
sig_result = @wallet.create_signature(sig_args)
|
|
195
|
+
sig_result = @wallet.create_signature(**sig_args)
|
|
196
196
|
field_sig = sig_result[:signature].pack('C*')
|
|
197
197
|
|
|
198
198
|
fields = [field_protocol, field_identity, field_domain, field_topic, field_sig]
|
data/lib/bsv/registry/client.rb
CHANGED
|
@@ -66,18 +66,16 @@ module BSV
|
|
|
66
66
|
|
|
67
67
|
basket_name = basket_name_for(definition_type)
|
|
68
68
|
create_result = @wallet.create_action(
|
|
69
|
-
{
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
options: { randomize_outputs: false }
|
|
80
|
-
},
|
|
69
|
+
description: "Register a new #{definition_type} definition",
|
|
70
|
+
outputs: [
|
|
71
|
+
{
|
|
72
|
+
satoshis: Constants::TOKEN_AMOUNT,
|
|
73
|
+
locking_script: locking_script.to_hex,
|
|
74
|
+
output_description: "New #{definition_type} registration token",
|
|
75
|
+
basket: basket_name
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
options: { randomize_outputs: false },
|
|
81
79
|
originator: @originator
|
|
82
80
|
)
|
|
83
81
|
|
|
@@ -122,7 +120,7 @@ module BSV
|
|
|
122
120
|
def list_own_registry_entries(definition_type)
|
|
123
121
|
basket_name = basket_name_for(definition_type)
|
|
124
122
|
list_result = @wallet.list_outputs(
|
|
125
|
-
|
|
123
|
+
basket: basket_name, include: 'entire transactions',
|
|
126
124
|
originator: @originator
|
|
127
125
|
)
|
|
128
126
|
|
|
@@ -160,18 +158,16 @@ module BSV
|
|
|
160
158
|
outpoint = "#{registered_definition.txid}.#{registered_definition.output_index}"
|
|
161
159
|
|
|
162
160
|
create_result = @wallet.create_action(
|
|
163
|
-
{
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
options: { randomize_outputs: false, no_send: true }
|
|
174
|
-
},
|
|
161
|
+
description: "Revoke #{definition_type} definition: #{item_identifier(registered_definition)}",
|
|
162
|
+
input_beef: registered_definition.beef,
|
|
163
|
+
inputs: [
|
|
164
|
+
{
|
|
165
|
+
outpoint: outpoint,
|
|
166
|
+
unlocking_script_length: BSV::Script::PushDropTemplate::Unlocker::ESTIMATED_LENGTH,
|
|
167
|
+
input_description: "Revoking #{definition_type} token"
|
|
168
|
+
}
|
|
169
|
+
],
|
|
170
|
+
options: { randomize_outputs: false, no_send: true },
|
|
175
171
|
originator: @originator
|
|
176
172
|
)
|
|
177
173
|
|
|
@@ -210,7 +206,7 @@ module BSV
|
|
|
210
206
|
def identity_key
|
|
211
207
|
return @identity_key if defined?(@identity_key)
|
|
212
208
|
|
|
213
|
-
result = @wallet.get_public_key(
|
|
209
|
+
result = @wallet.get_public_key(identity_key: true, originator: @originator)
|
|
214
210
|
@identity_key = result[:public_key] || result['public_key'] || result['publicKey'] || result[:publicKey]
|
|
215
211
|
end
|
|
216
212
|
|
|
@@ -561,7 +557,7 @@ module BSV
|
|
|
561
557
|
#
|
|
562
558
|
# @return [Symbol] :mainnet or :testnet
|
|
563
559
|
def wallet_network
|
|
564
|
-
result = @wallet.get_network(
|
|
560
|
+
result = @wallet.get_network(originator: @originator)
|
|
565
561
|
net_str = result[:network] || result['network'] || 'mainnet'
|
|
566
562
|
net_str.to_sym
|
|
567
563
|
end
|
|
@@ -108,14 +108,14 @@ module BSV
|
|
|
108
108
|
counterparty: @counterparty
|
|
109
109
|
}
|
|
110
110
|
orig_kw = @originator ? { originator: @originator } : {}
|
|
111
|
-
result = @wallet.create_signature(sig_args, **orig_kw)
|
|
111
|
+
result = @wallet.create_signature(**sig_args, **orig_kw)
|
|
112
112
|
|
|
113
113
|
sig_bytes = result[:signature].pack('C*')
|
|
114
114
|
sig_with_hashtype = sig_bytes + [sighash_type].pack('C')
|
|
115
115
|
|
|
116
116
|
# Fetch the derived public key so the P2PKH unlock can include it
|
|
117
117
|
pub_args = { protocol_id: @protocol_id, key_id: @key_id, counterparty: @counterparty }
|
|
118
|
-
pub_result = @wallet.get_public_key(pub_args, **orig_kw)
|
|
118
|
+
pub_result = @wallet.get_public_key(**pub_args, **orig_kw)
|
|
119
119
|
pubkey_bytes = [pub_result[:public_key]].pack('H*')
|
|
120
120
|
|
|
121
121
|
BSV::Script::Script.pushdrop_unlock(
|
|
@@ -176,7 +176,7 @@ module BSV
|
|
|
176
176
|
else
|
|
177
177
|
pub_args = { protocol_id: protocol_id, key_id: key_id, counterparty: counterparty }
|
|
178
178
|
orig_kw = @originator ? { originator: @originator } : {}
|
|
179
|
-
pub_result = @wallet.get_public_key(pub_args, **orig_kw)
|
|
179
|
+
pub_result = @wallet.get_public_key(**pub_args, **orig_kw)
|
|
180
180
|
[pub_result[:public_key]].pack('H*')
|
|
181
181
|
end
|
|
182
182
|
|
|
@@ -187,7 +187,7 @@ module BSV
|
|
|
187
187
|
data_to_sign = all_fields.reduce(''.b) { |acc, f| acc + f }.unpack('C*')
|
|
188
188
|
sig_args = { data: data_to_sign, protocol_id: protocol_id, key_id: key_id, counterparty: counterparty }
|
|
189
189
|
orig_kw = @originator ? { originator: @originator } : {}
|
|
190
|
-
sig_result = @wallet.create_signature(sig_args, **orig_kw)
|
|
190
|
+
sig_result = @wallet.create_signature(**sig_args, **orig_kw)
|
|
191
191
|
all_fields << sig_result[:signature].pack('C*')
|
|
192
192
|
end
|
|
193
193
|
|
data/lib/bsv/version.rb
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BSV
|
|
4
|
+
module Wallet
|
|
5
|
+
# Base error for all wallet operations. Carries a machine-readable code
|
|
6
|
+
# per the BRC-100 error structure.
|
|
7
|
+
class Error < StandardError
|
|
8
|
+
attr_reader :code
|
|
9
|
+
|
|
10
|
+
def initialize(message, code = 1)
|
|
11
|
+
@code = code
|
|
12
|
+
super(message)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Raised when a required parameter is missing or invalid.
|
|
17
|
+
class InvalidParameterError < Error
|
|
18
|
+
attr_reader :parameter
|
|
19
|
+
|
|
20
|
+
def initialize(parameter, must_be = 'valid')
|
|
21
|
+
@parameter = parameter
|
|
22
|
+
super("the #{parameter} parameter must be #{must_be}", 6)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Raised when an HMAC fails to verify.
|
|
27
|
+
class InvalidHmacError < Error
|
|
28
|
+
def initialize(message = 'the provided HMAC is invalid')
|
|
29
|
+
super(message, 3)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Raised when a signature fails to verify.
|
|
34
|
+
class InvalidSignatureError < Error
|
|
35
|
+
def initialize(message = 'the provided signature is invalid')
|
|
36
|
+
super(message, 4)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Raised when an operation is not supported by this wallet implementation.
|
|
41
|
+
class UnsupportedActionError < Error
|
|
42
|
+
def initialize(method_name = 'this method')
|
|
43
|
+
super("#{method_name} is not supported by this wallet implementation", 2)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|