Class: Ethereum::ABI::ContractTranslator
- Defined in:
- lib/ethereum/abi/contract_translator.rb
Instance Method Summary collapse
- #constructor_data ⇒ Object
-
#decode_event(log_topics, log_data) ⇒ Object
Return a dictionary represent the log.
-
#decode_function_result(name, data) ⇒ Array[Object]
(also: #decode)
Return the function call result decoded.
-
#encode(name, args) ⇒ String
Return the encoded function call.
-
#encode_constructor_arguments(args) ⇒ Object
Return the encoded constructor call.
- #event(name, encode_types) ⇒ Object
- #event_data ⇒ Object
- #event_id(name, encode_types) ⇒ Object
- #function(name) ⇒ Object
- #function_data ⇒ Object
-
#initialize(contract_interface) ⇒ ContractTranslator
constructor
A new instance of ContractTranslator.
-
#listen(log, noprint: true) ⇒ Object
. Return a dictionary representation of the Log instance.
Note: this function won't work with anonymous events.. - #method_id(name, encode_types) ⇒ Object
Constructor Details
#initialize(contract_interface) ⇒ ContractTranslator
Returns a new instance of ContractTranslator.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/ethereum/abi/contract_translator.rb', line 9 def initialize(contract_interface) if contract_interface.instance_of?(String) contract_interface = JSON.parse contract_interface end @contract = { fallback_data: nil, constructor_data: nil, function_data: {}, event_data: {} } contract_interface.each do |desc| type = desc['type'] || 'function' encode_types = [] signature = [] if type != 'fallback' && desc.has_key?('inputs') encode_types = desc['inputs'].map {|e| e['type'] } signature = desc['inputs'].map {|e| [e['type'], e['name']] } end case type when 'function' name = basename desc['name'] decode_types = desc['outputs'].map {|e| e['type'] } @contract[:function_data][name] = { prefix: method_id(name, encode_types), encode_types: encode_types, decode_types: decode_types, is_constant: desc.fetch('constant', false), signature: signature, payable: desc.fetch('payable', false) } when 'event' name = basename desc['name'] indexed = desc['inputs'].map {|e| e['indexed'] } names = desc['inputs'].map {|e| e['name'] } @contract[:event_data][event_id(name, encode_types)] = { types: encode_types, name: name, names: names, indexed: indexed, anonymous: desc.fetch('anonymous', false) } when 'constructor' raise ValueError, "Only one constructor is supported." if @contract[:constructor_data] @contract[:constructor_data] = { encode_types: encode_types, signature: signature } when 'fallback' raise ValueError, "Only one fallback function is supported." if @contract[:fallback_data] @contract[:fallback_data] = { payable: desc['payable'] } else raise ValueError, "Unknown interface type: #{type}" end end end |
Instance Method Details
#constructor_data ⇒ Object
175 176 177 |
# File 'lib/ethereum/abi/contract_translator.rb', line 175 def constructor_data @contract[:constructor_data] end |
#decode_event(log_topics, log_data) ⇒ Object
Return a dictionary represent the log.
Notes: this function won’t work with anonymous events.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/ethereum/abi/contract_translator.rb', line 125 def decode_event(log_topics, log_data) # topics[0]: keccak256(normalized_event_name) raise ValueError, "Unknown log type" unless log_topics.size > 0 && event_data.has_key?(log_topics[0]) event_id = log_topics[0] event = event_data[event_id] names = event[:names] types = event[:types] indexed = event[:indexed] unindexed_types = types.zip(indexed).select {|(t, i)| i.false? }.map(&:first) unindexed_args = ABI.decode_abi unindexed_types, log_data result = {} indexed_count = 1 # skip topics[0] names.each_with_index do |name, i| v = if indexed[i].true? topic_bytes = Utils.zpad_int log_topics[indexed_count] indexed_count += 1 ABI.decode_primitive_type ABI::Type.parse(types[i]), topic_bytes else unindexed_args.shift end result[name] = v end result['_event_type'] = event[:name] result end |
#decode_function_result(name, data) ⇒ Array[Object] Also known as: decode
Return the function call result decoded.
111 112 113 114 |
# File 'lib/ethereum/abi/contract_translator.rb', line 111 def decode_function_result(name, data) desc = function_data[name] ABI.decode_abi desc[:decode_types], data end |
#encode(name, args) ⇒ String
Return the encoded function call.
83 84 85 86 87 88 89 90 91 |
# File 'lib/ethereum/abi/contract_translator.rb', line 83 def encode(name, args) raise ValueError, "Unknown function #{name}" unless function_data.include?(name) desc = function_data[name] func_id = Utils.zpad(Utils.encode_int(desc[:prefix]), 4) calldata = ABI.encode_abi desc[:encode_types], args "#{func_id}#{calldata}" end |
#encode_constructor_arguments(args) ⇒ Object
Return the encoded constructor call.
96 97 98 99 100 |
# File 'lib/ethereum/abi/contract_translator.rb', line 96 def encode_constructor_arguments(args) raise ValueError, "The contract interface didn't have a constructor" unless constructor_data ABI.encode_abi constructor_data[:encode_types], args end |
#event(name, encode_types) ⇒ Object
191 192 193 |
# File 'lib/ethereum/abi/contract_translator.rb', line 191 def event(name, encode_types) event_data[event_id(name, encode_types)] end |
#event_data ⇒ Object
183 184 185 |
# File 'lib/ethereum/abi/contract_translator.rb', line 183 def event_data @contract[:event_data] end |
#event_id(name, encode_types) ⇒ Object
199 200 201 |
# File 'lib/ethereum/abi/contract_translator.rb', line 199 def event_id(name, encode_types) Utils.big_endian_to_int Utils.keccak256(get_sig(name, encode_types)) end |
#function(name) ⇒ Object
187 188 189 |
# File 'lib/ethereum/abi/contract_translator.rb', line 187 def function(name) function_data[name] end |
#function_data ⇒ Object
179 180 181 |
# File 'lib/ethereum/abi/contract_translator.rb', line 179 def function_data @contract[:function_data] end |
#listen(log, noprint: true) ⇒ Object
. Return a dictionary representation of the Log instance.
Note: this function won’t work with anonymous events.
166 167 168 169 170 171 172 173 |
# File 'lib/ethereum/abi/contract_translator.rb', line 166 def listen(log, noprint: true) result = decode_event log.topics, log.data p result if result['_from'] = Utils.encode_hex(log.address) result rescue ValueError nil # api compatibility end |
#method_id(name, encode_types) ⇒ Object
195 196 197 |
# File 'lib/ethereum/abi/contract_translator.rb', line 195 def method_id(name, encode_types) Utils.big_endian_to_int Utils.keccak256(get_sig(name, encode_types))[0,4] end |