bsv-sdk 0.4.0 → 0.5.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 +30 -0
- data/lib/bsv/identity/client.rb +353 -0
- data/lib/bsv/identity/constants.rb +41 -0
- data/lib/bsv/identity/identity_parser.rb +247 -0
- data/lib/bsv/identity/types.rb +118 -0
- data/lib/bsv/identity.rb +18 -0
- data/lib/bsv/overlay/admin_token_template.rb +249 -0
- data/lib/bsv/overlay/broadcast_facilitator.rb +134 -0
- data/lib/bsv/overlay/constants.rb +52 -0
- data/lib/bsv/overlay/errors.rb +17 -0
- data/lib/bsv/overlay/host_reputation_tracker.rb +266 -0
- data/lib/bsv/overlay/lookup_facilitator.rb +125 -0
- data/lib/bsv/overlay/lookup_resolver.rb +406 -0
- data/lib/bsv/overlay/topic_broadcaster.rb +402 -0
- data/lib/bsv/overlay/types.rb +111 -0
- data/lib/bsv/overlay.rb +29 -0
- data/lib/bsv/script/push_drop_template.rb +207 -0
- data/lib/bsv/script.rb +6 -4
- data/lib/bsv/version.rb +1 -1
- data/lib/bsv/wallet_interface/proto_wallet.rb +9 -9
- data/lib/bsv-sdk.rb +2 -0
- metadata +18 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e6f6657530a3e07510c21eeb919dd276a99b680a825b1d63c8e3c05731f36107
|
|
4
|
+
data.tar.gz: 0e44275e673ea30e56d4996d1f21e98e8bb22803815da60ab1f32fefcc61b327
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1e3bbb1cf676054dbf64cfcb94d3edd33e290f9d64734ec828ed1673b97f65ddb25b83e087e6e592ca036d1699a4ded46c974491f6a828b975b2c739e57e214e
|
|
7
|
+
data.tar.gz: 0de23da3bb0755d7dcf515f75638286479828c6dac0957532aedbfe28abad6bf8efee8c13b8092e5d05826559fdb16f7c102b84c242885b089022f90b638de05
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,36 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.5.0] - 2026-04-04
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
#### Overlay
|
|
13
|
+
|
|
14
|
+
- **SHIP/SLAP overlay services** — `BSV::Overlay` module for topic-based transaction broadcasting and service discovery.
|
|
15
|
+
- `TopicBroadcaster` (aliased as `SHIPBroadcaster`) — broadcasts tagged BEEF to topic-interested hosts with configurable acknowledgement modes (all/any/specific hosts) and STEAK response parsing.
|
|
16
|
+
- `LookupResolver` — discovers competent hosts via SLAP trackers, queries in parallel, aggregates and deduplicates results. TTL-based host caching.
|
|
17
|
+
- `HostReputationTracker` — EWMA latency scoring with exponential backoff, DNS error escalation, thread-safe. Optional persistence via injectable store adapter.
|
|
18
|
+
- `AdminTokenTemplate` — decode/lock/unlock for SHIP/SLAP advertisement PushDrop tokens with BRC-42 wallet key derivation.
|
|
19
|
+
- Abstract base classes (`LookupFacilitator`, `BroadcastFacilitator`) with default HTTPS implementations — all dependencies injectable via constructor.
|
|
20
|
+
- SSRF protection for SLAP-discovered domains (private/loopback IP rejection).
|
|
21
|
+
|
|
22
|
+
#### Identity
|
|
23
|
+
|
|
24
|
+
- **Identity client** — `BSV::Identity` module for certificate-based identity resolution and publication.
|
|
25
|
+
- `Client` — resolve identities by key or attributes, publicly reveal certificate fields on-chain, revoke revelations. All overlay dependencies injectable.
|
|
26
|
+
- `IdentityParser` — converts identity certificates to `DisplayableIdentity`, handling all 9 known types (xCert, discordCert, phoneCert, emailCert, identiCert, registrant, coolCert, anyone, self) plus generic field-name heuristic fallback.
|
|
27
|
+
- Types: `DisplayableIdentity`, `IdentityCertificate`, `CertifierInfo`, `ClientOptions` with cross-SDK constant alignment.
|
|
28
|
+
- Certificate verifier injectable with safe-by-default (raises `NotImplementedError`).
|
|
29
|
+
|
|
30
|
+
#### Script
|
|
31
|
+
|
|
32
|
+
- **PushDropTemplate** — reusable wallet-aware PushDrop template with BRC-42 key derivation, optional ECDSA field signing, and P2PKH lock/unlock. Used by Identity client, reusable for ContactsManager and other PushDrop-based features.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- `ProtoWallet` parameter name mismatch: `_originator:` → `originator:` to match the `WalletInterface` contract.
|
|
37
|
+
|
|
8
38
|
## [0.4.0] - 2026-04-01
|
|
9
39
|
|
|
10
40
|
### Added
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module BSV
|
|
6
|
+
module Identity
|
|
7
|
+
# Client for resolving and publishing identity information on the BSV overlay network.
|
|
8
|
+
#
|
|
9
|
+
# Wraps wallet discovery and overlay broadcasting to provide a high-level
|
|
10
|
+
# interface for the BSV Identity protocol:
|
|
11
|
+
#
|
|
12
|
+
# - Resolve identities by key or attributes via {#resolve_by_identity_key} and
|
|
13
|
+
# {#resolve_by_attributes}.
|
|
14
|
+
# - Publicly reveal certificate fields on-chain via {#publicly_reveal_attributes}.
|
|
15
|
+
# - Revoke an existing revelation via {#revoke_certificate_revelation}.
|
|
16
|
+
#
|
|
17
|
+
# All overlay dependencies (broadcaster, resolver) are injectable for testing.
|
|
18
|
+
#
|
|
19
|
+
# @example Resolve an identity
|
|
20
|
+
# client = BSV::Identity::Client.new(wallet: my_wallet)
|
|
21
|
+
# identities = client.resolve_by_identity_key(identity_key: pubkey_hex)
|
|
22
|
+
#
|
|
23
|
+
# @example Publicly reveal certificate fields
|
|
24
|
+
# client = BSV::Identity::Client.new(wallet: my_wallet, broadcaster: my_broadcaster)
|
|
25
|
+
# result = client.publicly_reveal_attributes(certificate, fields_to_reveal: ['email'])
|
|
26
|
+
class Client
|
|
27
|
+
# Default certificate verifier — raises NotImplementedError because certificate
|
|
28
|
+
# verification depends on BSV::Auth::Certificate, which is a separate HLR.
|
|
29
|
+
DEFAULT_VERIFIER = lambda do |_certificate|
|
|
30
|
+
raise NotImplementedError,
|
|
31
|
+
'Certificate verification requires BSV::Auth::Certificate (not yet implemented)'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @param wallet [#discover_by_identity_key, #discover_by_attributes,
|
|
35
|
+
# #prove_certificate, #create_action, #get_network] BRC-100 wallet interface
|
|
36
|
+
# @param options [ClientOptions, nil] identity protocol options (default: ClientOptions::DEFAULT)
|
|
37
|
+
# @param originator [String, nil] optional FQDN of the originating application
|
|
38
|
+
# @param certificate_verifier [#call, nil] callable that verifies a certificate;
|
|
39
|
+
# defaults to a lambda that raises NotImplementedError
|
|
40
|
+
# @param broadcaster [BSV::Overlay::TopicBroadcaster, nil] injectable broadcaster;
|
|
41
|
+
# built from the wallet's network preset when nil
|
|
42
|
+
# @param resolver [BSV::Overlay::LookupResolver, nil] injectable lookup resolver;
|
|
43
|
+
# built from the wallet's network preset when nil
|
|
44
|
+
def initialize(
|
|
45
|
+
wallet:,
|
|
46
|
+
options: nil,
|
|
47
|
+
originator: nil,
|
|
48
|
+
certificate_verifier: nil,
|
|
49
|
+
broadcaster: nil,
|
|
50
|
+
resolver: nil
|
|
51
|
+
)
|
|
52
|
+
@wallet = wallet
|
|
53
|
+
@options = options || default_options
|
|
54
|
+
@originator = originator
|
|
55
|
+
@certificate_verifier = certificate_verifier || DEFAULT_VERIFIER
|
|
56
|
+
@broadcaster = broadcaster
|
|
57
|
+
@resolver = resolver
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Resolves displayable identities issued to a given identity key.
|
|
61
|
+
#
|
|
62
|
+
# Delegates to the wallet's +discover_by_identity_key+ and maps each
|
|
63
|
+
# returned certificate through {IdentityParser.parse}.
|
|
64
|
+
#
|
|
65
|
+
# @param identity_key [String] compressed public key hex
|
|
66
|
+
# @param limit [Integer, nil] maximum number of certificates to return
|
|
67
|
+
# @param offset [Integer, nil] number of certificates to skip
|
|
68
|
+
# @return [Array<DisplayableIdentity>]
|
|
69
|
+
def resolve_by_identity_key(identity_key:, limit: nil, offset: nil)
|
|
70
|
+
args = { identity_key: identity_key }
|
|
71
|
+
args[:limit] = limit unless limit.nil?
|
|
72
|
+
args[:offset] = offset unless offset.nil?
|
|
73
|
+
|
|
74
|
+
result = @wallet.discover_by_identity_key(args, originator: @originator)
|
|
75
|
+
parse_certificates(result)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Resolves displayable identities matching specific certificate attribute values.
|
|
79
|
+
#
|
|
80
|
+
# Delegates to the wallet's +discover_by_attributes+ and maps each
|
|
81
|
+
# returned certificate through {IdentityParser.parse}.
|
|
82
|
+
#
|
|
83
|
+
# @param attributes [Hash] field name/value pairs to match
|
|
84
|
+
# @param limit [Integer, nil] maximum number of certificates to return
|
|
85
|
+
# @param offset [Integer, nil] number of certificates to skip
|
|
86
|
+
# @return [Array<DisplayableIdentity>]
|
|
87
|
+
def resolve_by_attributes(attributes:, limit: nil, offset: nil)
|
|
88
|
+
args = { attributes: attributes }
|
|
89
|
+
args[:limit] = limit unless limit.nil?
|
|
90
|
+
args[:offset] = offset unless offset.nil?
|
|
91
|
+
|
|
92
|
+
result = @wallet.discover_by_attributes(args, originator: @originator)
|
|
93
|
+
parse_certificates(result)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Publicly reveals selected fields from a certificate by creating an
|
|
97
|
+
# on-chain identity token and broadcasting it to the overlay network.
|
|
98
|
+
#
|
|
99
|
+
# The certificate is first optionally verified via the injected verifier,
|
|
100
|
+
# then the wallet proves the selected fields to the "anyone" verifier
|
|
101
|
+
# (PrivateKey(1) public key). A PushDrop locking script is constructed from
|
|
102
|
+
# the certificate JSON plus keyring, and the resulting transaction is
|
|
103
|
+
# broadcast to +tm_identity+.
|
|
104
|
+
#
|
|
105
|
+
# @param certificate [Hash] wallet certificate hash
|
|
106
|
+
# @param fields_to_reveal [Array<String>] field names to include in the revelation
|
|
107
|
+
# @return [BSV::Overlay::OverlayBroadcastResult]
|
|
108
|
+
# @raise [ArgumentError] if the certificate has no fields or fields_to_reveal is empty
|
|
109
|
+
# @raise [RuntimeError] if certificate verification fails or create_action returns no tx
|
|
110
|
+
def publicly_reveal_attributes(certificate, fields_to_reveal:)
|
|
111
|
+
fields = certificate[:fields] || certificate['fields'] || {}
|
|
112
|
+
raise ArgumentError, 'Public reveal failed: Certificate has no fields to reveal!' if fields.empty?
|
|
113
|
+
raise ArgumentError, 'Public reveal failed: You must reveal at least one field!' if fields_to_reveal.empty?
|
|
114
|
+
|
|
115
|
+
verify_certificate(certificate)
|
|
116
|
+
|
|
117
|
+
# Prove the certificate to the "anyone" verifier (PrivateKey(1) public key)
|
|
118
|
+
anyone_pubkey = BSV::Script::PushDropTemplate::GENERATOR_PUBKEY_HEX
|
|
119
|
+
prove_result = @wallet.prove_certificate(
|
|
120
|
+
{ certificate: certificate, fields_to_reveal: fields_to_reveal, verifier: anyone_pubkey },
|
|
121
|
+
originator: @originator
|
|
122
|
+
)
|
|
123
|
+
keyring = prove_result[:keyring_for_verifier]
|
|
124
|
+
|
|
125
|
+
# Build the PushDrop payload with ONLY the revealed fields — never
|
|
126
|
+
# broadcast the full certificate (encrypted values for unrevealed
|
|
127
|
+
# fields must not be written on-chain).
|
|
128
|
+
revealed_fields = fields_to_reveal.each_with_object({}) do |name, h|
|
|
129
|
+
h[name] = fields[name.to_s] || fields[name.to_sym]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
payload = JSON.generate(
|
|
133
|
+
type: certificate[:type] || certificate['type'],
|
|
134
|
+
serialNumber: certificate[:serial_number] || certificate['serial_number'] || certificate[:serialNumber] || certificate['serialNumber'],
|
|
135
|
+
subject: certificate[:subject] || certificate['subject'],
|
|
136
|
+
certifier: certificate[:certifier] || certificate['certifier'],
|
|
137
|
+
revocationOutpoint: certificate[:revocation_outpoint] || certificate['revocation_outpoint'] || certificate[:revocationOutpoint] || certificate['revocationOutpoint'],
|
|
138
|
+
fields: revealed_fields,
|
|
139
|
+
keyring: keyring
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Construct the locking script via PushDropTemplate
|
|
143
|
+
template = BSV::Script::PushDropTemplate.new(wallet: @wallet, originator: @originator)
|
|
144
|
+
locking_script = template.lock(
|
|
145
|
+
fields: [payload],
|
|
146
|
+
protocol_id: @options.protocol_id,
|
|
147
|
+
key_id: @options.key_id,
|
|
148
|
+
counterparty: 'anyone'
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Create the transaction
|
|
152
|
+
create_result = @wallet.create_action(
|
|
153
|
+
{
|
|
154
|
+
description: 'Create a new Identity Token',
|
|
155
|
+
outputs: [
|
|
156
|
+
{
|
|
157
|
+
satoshis: @options.token_amount,
|
|
158
|
+
locking_script: locking_script.to_hex,
|
|
159
|
+
output_description: 'Identity Token'
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
options: { randomize_outputs: false }
|
|
163
|
+
},
|
|
164
|
+
originator: @originator
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
raise 'Public reveal failed: failed to create action!' if create_result[:tx].nil?
|
|
168
|
+
|
|
169
|
+
tx = BSV::Transaction::Transaction.from_beef(create_result[:tx])
|
|
170
|
+
broadcaster_for_action.broadcast(tx)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Revokes a publicly revealed certificate by spending the identity token.
|
|
174
|
+
#
|
|
175
|
+
# Queries the +ls_identity+ lookup service for the revelation output identified
|
|
176
|
+
# by +serial_number+, then creates a spending transaction via the wallet and
|
|
177
|
+
# broadcasts it to +tm_identity+.
|
|
178
|
+
#
|
|
179
|
+
# @param serial_number [String] Base64 serial number of the certificate revelation to revoke
|
|
180
|
+
# @return [void]
|
|
181
|
+
# @raise [RuntimeError] if the revelation cannot be found or the transaction cannot be created
|
|
182
|
+
def revoke_certificate_revelation(serial_number)
|
|
183
|
+
question = BSV::Overlay::LookupQuestion.new(
|
|
184
|
+
service: Constants::SERVICE,
|
|
185
|
+
query: { serial_number: serial_number }
|
|
186
|
+
)
|
|
187
|
+
answer = resolver_for_action.query(question)
|
|
188
|
+
|
|
189
|
+
raise 'Revoke failed: could not find revelation output' unless answer.type == 'output-list'
|
|
190
|
+
raise 'Revoke failed: no outputs found for serial number' if answer.outputs.empty?
|
|
191
|
+
|
|
192
|
+
output = answer.outputs.first
|
|
193
|
+
beef_bytes = output['beef'] || output[:beef]
|
|
194
|
+
raise 'Revoke failed: overlay response missing BEEF data' unless beef_bytes
|
|
195
|
+
|
|
196
|
+
raw_idx = output['outputIndex'] || output[:output_index]
|
|
197
|
+
raise 'Revoke failed: overlay response missing outputIndex' if raw_idx.nil?
|
|
198
|
+
|
|
199
|
+
output_idx = raw_idx.to_i
|
|
200
|
+
raise 'Revoke failed: invalid outputIndex from overlay' if output_idx.negative?
|
|
201
|
+
|
|
202
|
+
beef = BSV::Transaction::Beef.from_binary(beef_bytes)
|
|
203
|
+
tx = beef.transactions.last&.transaction
|
|
204
|
+
raise 'Revoke failed: no transaction found in BEEF' unless tx
|
|
205
|
+
raise 'Revoke failed: outputIndex out of range' if output_idx >= tx.outputs.length
|
|
206
|
+
txid = tx.txid_hex
|
|
207
|
+
outpoint = "#{txid}.#{output_idx}"
|
|
208
|
+
|
|
209
|
+
# Create a spending transaction; use unlocking_script_length so the wallet
|
|
210
|
+
# produces a signable transaction that can then be signed and broadcast.
|
|
211
|
+
create_result = @wallet.create_action(
|
|
212
|
+
{
|
|
213
|
+
description: 'Spend certificate revelation token',
|
|
214
|
+
input_beef: beef_bytes,
|
|
215
|
+
inputs: [
|
|
216
|
+
{
|
|
217
|
+
input_description: 'Revelation token',
|
|
218
|
+
outpoint: outpoint,
|
|
219
|
+
unlocking_script_length: BSV::Script::PushDropTemplate::Unlocker::ESTIMATED_LENGTH
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
options: { randomize_outputs: false, no_send: true }
|
|
223
|
+
},
|
|
224
|
+
originator: @originator
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
raise 'Revoke failed: failed to create signable transaction' if create_result[:signable_transaction].nil?
|
|
228
|
+
|
|
229
|
+
signable = create_result[:signable_transaction]
|
|
230
|
+
partial_tx = BSV::Transaction::Transaction.from_beef(signable[:tx])
|
|
231
|
+
|
|
232
|
+
# Unlock via PushDrop
|
|
233
|
+
template = BSV::Script::PushDropTemplate.new(wallet: @wallet, originator: @originator)
|
|
234
|
+
unlocker = template.unlock(
|
|
235
|
+
protocol_id: @options.protocol_id,
|
|
236
|
+
key_id: @options.key_id,
|
|
237
|
+
counterparty: 'anyone'
|
|
238
|
+
)
|
|
239
|
+
# Sign the first (and only) input in the spending transaction.
|
|
240
|
+
# output_idx is the index in the *source* tx; the spending tx input is always 0.
|
|
241
|
+
spending_input_idx = 0
|
|
242
|
+
unlocking_script = unlocker.sign(partial_tx, spending_input_idx)
|
|
243
|
+
|
|
244
|
+
sign_result = @wallet.sign_action(
|
|
245
|
+
{
|
|
246
|
+
reference: signable[:reference],
|
|
247
|
+
spends: { spending_input_idx => { unlocking_script: unlocking_script.to_hex } },
|
|
248
|
+
options: { no_send: true }
|
|
249
|
+
},
|
|
250
|
+
originator: @originator
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
raise 'Revoke failed: failed to sign transaction' if sign_result[:tx].nil?
|
|
254
|
+
|
|
255
|
+
signed_tx = BSV::Transaction::Transaction.from_beef(sign_result[:tx])
|
|
256
|
+
broadcaster_for_action.broadcast(signed_tx)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
private
|
|
260
|
+
|
|
261
|
+
# Maps an array of raw certificate hashes to DisplayableIdentity objects.
|
|
262
|
+
#
|
|
263
|
+
# Each certificate hash (as returned by the wallet's discovery methods) is
|
|
264
|
+
# wrapped in an IdentityCertificate and parsed via IdentityParser.
|
|
265
|
+
#
|
|
266
|
+
# @param result [Hash, nil] wallet discovery result with :certificates key
|
|
267
|
+
# @return [Array<DisplayableIdentity>]
|
|
268
|
+
def parse_certificates(result)
|
|
269
|
+
certs = result && result[:certificates]
|
|
270
|
+
return [] if certs.nil? || certs.empty?
|
|
271
|
+
|
|
272
|
+
certs.map { |cert| IdentityParser.parse(wrap_certificate(cert)) }
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Wraps a raw certificate hash in an IdentityCertificate, extracting
|
|
276
|
+
# decrypted_fields and certifier_info where present.
|
|
277
|
+
#
|
|
278
|
+
# @param cert [Hash] raw certificate hash from the wallet
|
|
279
|
+
# @return [IdentityCertificate]
|
|
280
|
+
def wrap_certificate(cert)
|
|
281
|
+
decrypted = cert[:decrypted_fields] || cert['decrypted_fields'] || {}
|
|
282
|
+
certifier_h = cert[:certifier_info] || cert['certifier_info'] || {}
|
|
283
|
+
|
|
284
|
+
certifier_info = if certifier_h && !certifier_h.empty?
|
|
285
|
+
CertifierInfo.new(
|
|
286
|
+
name: certifier_h[:name] || certifier_h['name'] || '',
|
|
287
|
+
icon_url: certifier_h[:icon_url] || certifier_h['icon_url']
|
|
288
|
+
)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
IdentityCertificate.new(
|
|
292
|
+
certificate: cert,
|
|
293
|
+
decrypted_fields: decrypted,
|
|
294
|
+
certifier_info: certifier_info
|
|
295
|
+
)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# Calls the injected certificate verifier, wrapping any errors in a
|
|
299
|
+
# standardised RuntimeError message.
|
|
300
|
+
#
|
|
301
|
+
# @param certificate [Hash]
|
|
302
|
+
# @raise [RuntimeError] if verification fails
|
|
303
|
+
def verify_certificate(certificate)
|
|
304
|
+
@certificate_verifier.call(certificate)
|
|
305
|
+
rescue NotImplementedError
|
|
306
|
+
raise
|
|
307
|
+
rescue StandardError => e
|
|
308
|
+
raise "Public reveal failed: Certificate verification failed! (#{e.message})"
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# Returns the broadcaster to use for overlay actions, building one from
|
|
312
|
+
# the wallet's network when no injectable broadcaster was provided.
|
|
313
|
+
#
|
|
314
|
+
# @return [BSV::Overlay::TopicBroadcaster]
|
|
315
|
+
def broadcaster_for_action
|
|
316
|
+
return @broadcaster if @broadcaster
|
|
317
|
+
|
|
318
|
+
network = wallet_network
|
|
319
|
+
BSV::Overlay::TopicBroadcaster.new(
|
|
320
|
+
[Constants::TOPIC],
|
|
321
|
+
network_preset: network
|
|
322
|
+
)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# Returns the lookup resolver to use for overlay queries, building one from
|
|
326
|
+
# the wallet's network when no injectable resolver was provided.
|
|
327
|
+
#
|
|
328
|
+
# @return [BSV::Overlay::LookupResolver]
|
|
329
|
+
def resolver_for_action
|
|
330
|
+
return @resolver if @resolver
|
|
331
|
+
|
|
332
|
+
network = wallet_network
|
|
333
|
+
BSV::Overlay::LookupResolver.new(network_preset: network)
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# Queries the wallet for the current network and converts the string to a symbol.
|
|
337
|
+
#
|
|
338
|
+
# @return [Symbol] :mainnet or :testnet
|
|
339
|
+
def wallet_network
|
|
340
|
+
result = @wallet.get_network({}, originator: @originator)
|
|
341
|
+
net_str = result[:network] || result['network'] || 'mainnet'
|
|
342
|
+
net_str.to_sym
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Returns the default ClientOptions.
|
|
346
|
+
#
|
|
347
|
+
# @return [ClientOptions]
|
|
348
|
+
def default_options
|
|
349
|
+
ClientOptions::DEFAULT
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BSV
|
|
4
|
+
module Identity
|
|
5
|
+
# Protocol constants and well-known values for the BSV Identity system.
|
|
6
|
+
module Constants
|
|
7
|
+
# Overlay topic name for identity transactions.
|
|
8
|
+
TOPIC = 'tm_identity'
|
|
9
|
+
|
|
10
|
+
# Lookup service identifier for identity queries.
|
|
11
|
+
SERVICE = 'ls_identity'
|
|
12
|
+
|
|
13
|
+
# Maps symbolic names to their Base64-encoded 32-byte certificate type identifiers.
|
|
14
|
+
#
|
|
15
|
+
# Values are byte-exact matches with the TS SDK (ts-sdk/src/identity/types/index.ts)
|
|
16
|
+
# and Go SDK (go-sdk/identity/types.go).
|
|
17
|
+
KNOWN_IDENTITY_TYPES = {
|
|
18
|
+
x_cert: 'vdDWvftf1H+5+ZprUw123kjHlywH+v20aPQTuXgMpNc=',
|
|
19
|
+
discord_cert: '2TgqRC35B1zehGmB21xveZNc7i5iqHc0uxMb+1NMPW4=',
|
|
20
|
+
phone_cert: 'mffUklUzxbHr65xLohn0hRL0Tq2GjW1GYF/OPfzqJ6A=',
|
|
21
|
+
email_cert: 'exOl3KM0dIJ04EW5pZgbZmPag6MdJXd3/a1enmUU/BA=',
|
|
22
|
+
identi_cert: 'z40BOInXkI8m7f/wBrv4MJ09bZfzZbTj2fJqCtONqCY=',
|
|
23
|
+
registrant: 'YoPsbfR6YQczjzPdHCoGC7nJsOdPQR50+SYqcWpJ0y0=',
|
|
24
|
+
cool_cert: 'AGfk/WrT1eBDXpz3mcw386Zww2HmqcIn3uY6x4Af1eo=',
|
|
25
|
+
anyone: 'mfkOMfLDQmrr3SBxBQ5WeE+6Hy3VJRFq6w4A5Ljtlis=',
|
|
26
|
+
self: 'Hkge6X5JRxt1cWXtHLCrSTg6dCVTxjQJJ48iOYd7n3g='
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
# Fallback identity used when no verified identity information is available.
|
|
30
|
+
DEFAULT_IDENTITY = DisplayableIdentity.new(
|
|
31
|
+
name: 'Unknown Identity',
|
|
32
|
+
avatar_url: 'XUUB8bbn9fEthk15Ge3zTQXypUShfC94vFjp65v7u5CQ8qkpxzst',
|
|
33
|
+
abbreviated_key: '',
|
|
34
|
+
identity_key: '',
|
|
35
|
+
badge_icon_url: 'XUUV39HVPkpmMzYNTx7rpKzJvXfeiVyQWg2vfSpjBAuhunTCA9uG',
|
|
36
|
+
badge_label: 'Not verified by anyone you trust.',
|
|
37
|
+
badge_click_url: 'https://projectbabbage.com/docs/unknown-identity'
|
|
38
|
+
).freeze
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|