Class: BSV::Network::Provider

Inherits:
Object
  • Object
show all
Defined in:
lib/bsv/network/provider.rb

Overview

Provider is a named configuration container that hosts one or more Protocol instances and dispatches commands to the appropriate protocol.

Protocols are registered via a block DSL or by calling #protocol directly after construction. For each command symbol, the first-registered protocol that serves it wins (first-registered-wins, no warning on duplicates).

Example

gorillapool = BSV::Network::Provider.new('GorillaPool') do |p|
  p.protocol Protocols::ARC,         base_url: 'https://arcade.gorillapool.io'
  p.protocol Protocols::Chaintracks, base_url: 'https://arcade.gorillapool.io'
  p.protocol Protocols::Ordinals,    base_url: 'https://ordinals.gorillapool.io'
end

result = gorillapool.call(:broadcast, tx)
result.success?  # => true

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, auth: :none, rate_limit: nil, &block) ⇒ Provider

Returns a new instance of Provider.

Parameters:

  • name (String)

    human-readable provider name (e.g. ‘GorillaPool’)

  • auth (Hash, Symbol) (defaults to: :none)

    authentication config or :none (default: :none). An empty hash or nil is treated as :none.

  • rate_limit (Numeric, nil) (defaults to: nil)

    maximum requests per second (nil = unlimited)

  • block (Proc)

    optional configuration block — yields self



32
33
34
35
36
37
38
39
# File 'lib/bsv/network/provider.rb', line 32

def initialize(name, auth: :none, rate_limit: nil, &block)
  @name           = name
  @auth           = normalise_auth(auth)
  @rate_limit     = rate_limit
  @protocols      = []
  @command_index  = {}
  block&.call(self)
end

Instance Attribute Details

#authObject (readonly)

Returns the value of attribute auth.



25
26
27
# File 'lib/bsv/network/provider.rb', line 25

def auth
  @auth
end

#nameObject (readonly)

Returns the value of attribute name.



25
26
27
# File 'lib/bsv/network/provider.rb', line 25

def name
  @name
end

#rate_limitObject (readonly)

Returns the value of attribute rate_limit.



25
26
27
# File 'lib/bsv/network/provider.rb', line 25

def rate_limit
  @rate_limit
end

Instance Method Details

#authenticated?Boolean

Returns true when the provider is configured with authentication credentials (i.e. auth is not :none and not an empty hash).

Returns:

  • (Boolean)


45
46
47
# File 'lib/bsv/network/provider.rb', line 45

def authenticated?
  @auth != :none
end

#call(command_name, *args, **kwargs) ⇒ Result::Success, ...

Dispatches a command to the first-registered protocol that serves it.

Parameters:

  • command_name (Symbol, String)

    command to invoke

  • args (Array)

    positional arguments forwarded to the protocol

  • kwargs (Hash)

    keyword arguments forwarded to the protocol

Returns:

Raises:

  • (ArgumentError)

    when no registered protocol serves the command



129
130
131
132
133
134
135
# File 'lib/bsv/network/provider.rb', line 129

def call(command_name, *args, **kwargs)
  sym      = command_name.to_sym
  instance = @command_index[sym]
  raise ArgumentError, "#{@name} does not provide command :#{sym}" unless instance

  instance.call(sym, *args, **kwargs)
end

#capability_matrixHash{Protocol => Array<Symbol>}

Returns a hash mapping each protocol instance to the sorted list of commands it actually serves within this provider (respecting first-registered-wins — a protocol that lost a command to an earlier registration is not listed for that command).

Protocols that serve no commands in this provider are omitted.

Returns:



102
103
104
105
106
107
108
109
# File 'lib/bsv/network/provider.rb', line 102

def capability_matrix
  matrix = {}
  @protocols.each do |proto|
    served = proto.class.commands.select { |cmd| @command_index[cmd] == proto }
    matrix[proto] = served.sort unless served.empty?
  end
  matrix
end

#commandsSet<Symbol>

Returns the set of all command symbols available on this provider.

Returns:

  • (Set<Symbol>)


81
82
83
# File 'lib/bsv/network/provider.rb', line 81

def commands
  Set.new(@command_index.keys)
end

#protocol(klass, **kwargs) ⇒ Protocol

Registers a protocol class with the provider.

The class is instantiated with the supplied kwargs. Its commands are indexed: each command not yet in the index is mapped to this instance. Commands already in the index are left unchanged (first-registered wins).

The provider remains mutable — protocol may be called after block execution.

Parameters:

  • klass (Class)

    a Protocol subclass

  • kwargs (Hash)

    keyword arguments forwarded to klass.new

Returns:

  • (Protocol)

    the newly created protocol instance



61
62
63
64
65
66
67
68
# File 'lib/bsv/network/provider.rb', line 61

def protocol(klass, **kwargs)
  instance = klass.new(**kwargs)
  @protocols << instance
  klass.commands.each do |cmd|
    @command_index[cmd] ||= instance
  end
  instance
end

#protocol_for(command_name) ⇒ Protocol?

Returns the protocol instance that serves a given command, or nil if no registered protocol handles it.

Parameters:

  • command_name (Symbol, String)

Returns:



90
91
92
# File 'lib/bsv/network/provider.rb', line 90

def protocol_for(command_name)
  @command_index[command_name.to_sym]
end

#protocolsArray<Protocol>

Returns a frozen copy of the registered protocol instances, in registration order.

Returns:



74
75
76
# File 'lib/bsv/network/provider.rb', line 74

def protocols
  @protocols.dup.freeze
end

#to_sString Also known as: inspect

Returns a human-readable representation of the provider.

Returns:

  • (String)


114
115
116
117
118
119
# File 'lib/bsv/network/provider.rb', line 114

def to_s
  protocol_summary = @protocols.map { |p| p.class.name&.split('::')&.last || p.class.to_s }.join(', ')
  auth_status      = authenticated? ? 'authenticated' : 'unauthenticated'
  rate_part        = @rate_limit.nil? ? '' : " rate_limit=#{@rate_limit}"
  "#<#{self.class} name=#{@name.inspect} auth=#{auth_status}#{rate_part} protocols=[#{protocol_summary}]>"
end