Class: BlockGiven::Abi::Interface
- Inherits:
-
Object
- Object
- BlockGiven::Abi::Interface
- Defined in:
- lib/block_given/abi/interface.rb
Overview
Parsed ABI: functions (with overload resolution), events and custom errors.
Instance Attribute Summary collapse
-
#constructor ⇒ Object
readonly
Returns the value of attribute constructor.
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
-
#events ⇒ Object
readonly
Returns the value of attribute events.
-
#functions ⇒ Object
readonly
Returns the value of attribute functions.
-
#raw ⇒ Object
readonly
Returns the value of attribute raw.
Class Method Summary collapse
- .load_definitions(source) ⇒ Object
-
.parse(source) ⇒ Object
Accepts an ABI Array, a Hardhat/Foundry artifact Hash (with "abi"), a JSON String or a Pathname.
Instance Method Summary collapse
- #error_by_selector(selector) ⇒ Object
- #event(name) ⇒ Object
- #event_by_topic(topic) ⇒ Object
-
#function(name, args: [], kwargs: {}) ⇒ Object
Finds a function by name (snake_case or camelCase) or by full signature ("transfer(address,uint256)").
- #function_by_selector(selector) ⇒ Object
- #function_by_signature(signature) ⇒ Object
- #function_names ⇒ Object
-
#initialize(definitions) ⇒ Interface
constructor
A new instance of Interface.
- #inspect ⇒ Object
Constructor Details
#initialize(definitions) ⇒ Interface
Returns a new instance of Interface.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/block_given/abi/interface.rb', line 30 def initialize(definitions) @raw = definitions.map { |d| d.transform_keys(&:to_s) } @functions = [] @events = [] @errors = [] @constructor = nil @raw.each do |definition| case definition["type"] when "function", nil then @functions << Function.new(definition) when "event" then @events << Event.new(definition) when "error" then @errors << CustomError.new(definition) when "constructor" then @constructor = definition end end @functions_by_name = @functions.group_by(&:ruby_name) end |
Instance Attribute Details
#constructor ⇒ Object (readonly)
Returns the value of attribute constructor.
9 10 11 |
# File 'lib/block_given/abi/interface.rb', line 9 def constructor @constructor end |
#errors ⇒ Object (readonly)
Returns the value of attribute errors.
9 10 11 |
# File 'lib/block_given/abi/interface.rb', line 9 def errors @errors end |
#events ⇒ Object (readonly)
Returns the value of attribute events.
9 10 11 |
# File 'lib/block_given/abi/interface.rb', line 9 def events @events end |
#functions ⇒ Object (readonly)
Returns the value of attribute functions.
9 10 11 |
# File 'lib/block_given/abi/interface.rb', line 9 def functions @functions end |
#raw ⇒ Object (readonly)
Returns the value of attribute raw.
9 10 11 |
# File 'lib/block_given/abi/interface.rb', line 9 def raw @raw end |
Class Method Details
.load_definitions(source) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/block_given/abi/interface.rb', line 18 def self.load_definitions(source) case source when Array then source when Hash then source["abi"] || source[:abi] || raise(AbiError, "Hash has no 'abi' key") when Pathname, File then load_definitions(JSON.parse(File.read(source))) when String then load_definitions(JSON.parse(source)) else raise AbiError, "cannot parse ABI from #{source.class}" end rescue JSON::ParserError => e raise AbiError, "invalid ABI JSON: #{e.message}" end |
.parse(source) ⇒ Object
Accepts an ABI Array, a Hardhat/Foundry artifact Hash (with "abi"), a JSON String or a Pathname.
12 13 14 15 16 |
# File 'lib/block_given/abi/interface.rb', line 12 def self.parse(source) return source if source.is_a?(Interface) new(load_definitions(source)) end |
Instance Method Details
#error_by_selector(selector) ⇒ Object
100 101 102 |
# File 'lib/block_given/abi/interface.rb', line 100 def error_by_selector(selector) @errors.find { |e| e.selector == selector.to_s.downcase } end |
#event(name) ⇒ Object
89 90 91 92 93 94 |
# File 'lib/block_given/abi/interface.rb', line 89 def event(name) name = name.to_s key = Utils.snake_case(name).to_sym @events.find { |e| e.ruby_name == key || e.signature == name } || raise(EventNotFoundError, "no event #{name.inspect} in ABI (known: #{@events.map(&:name).join(', ')})") end |
#event_by_topic(topic) ⇒ Object
96 97 98 |
# File 'lib/block_given/abi/interface.rb', line 96 def event_by_topic(topic) @events.find { |e| e.topic == topic.to_s.downcase } end |
#function(name, args: [], kwargs: {}) ⇒ Object
Finds a function by name (snake_case or camelCase) or by full signature ("transfer(address,uint256)"). Overloads are disambiguated by argument count or keyword names.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/block_given/abi/interface.rb', line 52 def function(name, args: [], kwargs: {}) name = name.to_s return function_by_signature(name) if name.include?("(") candidates = @functions_by_name[Utils.snake_case(name).to_sym] if candidates.nil? raise FunctionNotFoundError, "no function #{name.inspect} in ABI (known: #{function_names.join(', ')})" end return candidates.first if candidates.size == 1 matching = if kwargs.empty? candidates.select { |f| f.inputs.size == args.size } else keys = kwargs.keys.map { |k| Utils.snake_case(k).to_sym }.sort candidates.select { |f| f.input_names.sort == keys } end return matching.first if matching.size == 1 if matching.size > 1 raise AmbiguousFunctionError, "#{name} is overloaded, use the full signature: #{candidates.map(&:signature).join(' | ')}" end raise FunctionNotFoundError, "no overload of #{name} matches the given arguments (#{candidates.map(&:signature).join(' | ')})" end |
#function_by_selector(selector) ⇒ Object
85 86 87 |
# File 'lib/block_given/abi/interface.rb', line 85 def function_by_selector(selector) @functions.find { |f| f.selector == selector.downcase } end |
#function_by_signature(signature) ⇒ Object
80 81 82 83 |
# File 'lib/block_given/abi/interface.rb', line 80 def function_by_signature(signature) @functions.find { |f| f.signature == signature.delete(" ") } || raise(FunctionNotFoundError, "no function with signature #{signature.inspect}") end |
#function_names ⇒ Object
47 |
# File 'lib/block_given/abi/interface.rb', line 47 def function_names = @functions_by_name.keys |
#inspect ⇒ Object
104 105 106 |
# File 'lib/block_given/abi/interface.rb', line 104 def inspect "#<BlockGiven::Abi::Interface functions=#{@functions.size} events=#{@events.size} errors=#{@errors.size}>" end |