eth-custom 0.5.7

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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.github/dependabot.yml +18 -0
  3. data/.github/workflows/codeql.yml +48 -0
  4. data/.github/workflows/docs.yml +26 -0
  5. data/.github/workflows/spec.yml +52 -0
  6. data/.gitignore +43 -0
  7. data/.gitmodules +3 -0
  8. data/.rspec +4 -0
  9. data/.yardopts +1 -0
  10. data/AUTHORS.txt +29 -0
  11. data/CHANGELOG.md +218 -0
  12. data/Gemfile +17 -0
  13. data/LICENSE.txt +202 -0
  14. data/README.md +347 -0
  15. data/Rakefile +6 -0
  16. data/bin/console +10 -0
  17. data/bin/setup +9 -0
  18. data/codecov.yml +6 -0
  19. data/eth.gemspec +51 -0
  20. data/lib/eth/abi/event.rb +137 -0
  21. data/lib/eth/abi/type.rb +178 -0
  22. data/lib/eth/abi.rb +446 -0
  23. data/lib/eth/address.rb +106 -0
  24. data/lib/eth/api.rb +223 -0
  25. data/lib/eth/chain.rb +157 -0
  26. data/lib/eth/client/http.rb +63 -0
  27. data/lib/eth/client/ipc.rb +50 -0
  28. data/lib/eth/client.rb +499 -0
  29. data/lib/eth/constant.rb +71 -0
  30. data/lib/eth/contract/event.rb +42 -0
  31. data/lib/eth/contract/function.rb +57 -0
  32. data/lib/eth/contract/function_input.rb +38 -0
  33. data/lib/eth/contract/function_output.rb +37 -0
  34. data/lib/eth/contract/initializer.rb +47 -0
  35. data/lib/eth/contract.rb +143 -0
  36. data/lib/eth/eip712.rb +184 -0
  37. data/lib/eth/key/decrypter.rb +146 -0
  38. data/lib/eth/key/encrypter.rb +207 -0
  39. data/lib/eth/key.rb +167 -0
  40. data/lib/eth/rlp/decoder.rb +114 -0
  41. data/lib/eth/rlp/encoder.rb +78 -0
  42. data/lib/eth/rlp/sedes/big_endian_int.rb +66 -0
  43. data/lib/eth/rlp/sedes/binary.rb +97 -0
  44. data/lib/eth/rlp/sedes/list.rb +84 -0
  45. data/lib/eth/rlp/sedes.rb +74 -0
  46. data/lib/eth/rlp.rb +63 -0
  47. data/lib/eth/signature.rb +163 -0
  48. data/lib/eth/solidity.rb +75 -0
  49. data/lib/eth/tx/eip1559.rb +337 -0
  50. data/lib/eth/tx/eip2930.rb +329 -0
  51. data/lib/eth/tx/legacy.rb +297 -0
  52. data/lib/eth/tx.rb +322 -0
  53. data/lib/eth/unit.rb +49 -0
  54. data/lib/eth/util.rb +235 -0
  55. data/lib/eth/version.rb +20 -0
  56. data/lib/eth.rb +35 -0
  57. metadata +184 -0
@@ -0,0 +1,137 @@
1
+ # Copyright (c) 2016-2022 The Ruby-Eth Contributors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # -*- encoding : ascii-8bit -*-
16
+
17
+ # Provides the {Eth} module.
18
+ module Eth
19
+
20
+ # Provides a Ruby implementation of the Ethereum Application Binary Interface (ABI).
21
+ module Abi
22
+
23
+ # Provides a module to decode transaction log events.
24
+ module Event
25
+ extend self
26
+
27
+ # Compute topic for ABI event interface.
28
+ #
29
+ # @param interface [Hash] ABI event interface.
30
+ # @return [String] a hex-string topic.
31
+ def compute_topic(interface)
32
+ sig = Abi.signature(interface)
33
+ Util.prefix_hex(Util.bin_to_hex(Util.keccak256(sig)))
34
+ end
35
+
36
+ # A decoded event log.
37
+ class LogDescription
38
+ # The event ABI interface used to decode the log.
39
+ attr_accessor :event_interface
40
+
41
+ # The the input argument of the event.
42
+ attr_accessor :args
43
+
44
+ # The named input argument of the event.
45
+ attr_accessor :kwargs
46
+
47
+ # The topic hash.
48
+ attr_accessor :topic
49
+
50
+ # Decodes event log argument values.
51
+ #
52
+ # @param event_interface [Hash] event ABI type.
53
+ # @param log [Hash] transaction receipt log
54
+ def initialize(event_interface, log)
55
+ @event_interface = event_interface
56
+
57
+ inputs = event_interface.fetch("inputs")
58
+ data = log.fetch("data")
59
+ topics = log.fetch("topics", [])
60
+ anonymous = event_interface.fetch("anonymous", false)
61
+
62
+ @topic = topics[0] if !anonymous
63
+ @args, @kwargs = Event.decode_log(inputs, data, topics, anonymous)
64
+ end
65
+
66
+ # The event name. (e.g. Transfer)
67
+ def name
68
+ @name ||= event_interface.fetch("name")
69
+ end
70
+
71
+ # The event signature. (e.g. Transfer(address,address,uint256))
72
+ def signature
73
+ @signature ||= Abi.signature(event_interface)
74
+ end
75
+ end
76
+
77
+ # Decodes a stream of receipt logs with a set of ABI interfaces.
78
+ #
79
+ # @param interfaces [Array] event ABI types.
80
+ # @param logs [Array] transaction receipt logs
81
+ # @return [Hash] an enumerator of LogDescription objects.
82
+ def decode_logs(interfaces, logs)
83
+ Enumerator.new do |y|
84
+ topic_to_interfaces = Hash[interfaces.map { |i| [compute_topic(i), i] }]
85
+
86
+ logs.each do |log|
87
+ topic = log.fetch("topics", [])[0]
88
+ if topic && interface = topic_to_interfaces[topic]
89
+ y << [log, LogDescription.new(interface, log)]
90
+ else
91
+ y << [log, nil]
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ # Decodes event log argument values.
98
+ #
99
+ # @param inputs [Array] event ABI types.
100
+ # @param data [String] ABI event data to be decoded.
101
+ # @param topics [Array] ABI event topics to be decoded.
102
+ # @param anonymous [Boolean] If event signature is excluded from topics.
103
+ # @return [[Array, Hash]] decoded positional arguments and decoded keyword arguments.
104
+ # @raise [DecodingError] if decoding fails for type.
105
+ def decode_log(inputs, data, topics, anonymous = false)
106
+ topic_inputs, data_inputs = inputs.partition { |i| i["indexed"] }
107
+
108
+ topic_types = topic_inputs.map { |i| i["type"] }
109
+ data_types = data_inputs.map { |i| i["type"] }
110
+
111
+ # If event is anonymous, all topics are arguments. Otherwise, the first
112
+ # topic will be the event signature.
113
+ if anonymous == false
114
+ topics = topics[1..-1]
115
+ end
116
+
117
+ decoded_topics = topics.map.with_index { |t, i| Abi.decode([topic_types[i]], t)[0] }
118
+ decoded_data = Abi.decode(data_types, data)
119
+
120
+ args = []
121
+ kwargs = {}
122
+
123
+ inputs.each_with_index do |input, index|
124
+ if input["indexed"]
125
+ value = decoded_topics[topic_inputs.index(input)]
126
+ else
127
+ value = decoded_data[data_inputs.index(input)]
128
+ end
129
+ args[index] = value
130
+ kwargs[input["name"].to_sym] = value
131
+ end
132
+
133
+ return args, kwargs
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,178 @@
1
+ # Copyright (c) 2016-2022 The Ruby-Eth Contributors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # -*- encoding : ascii-8bit -*-
16
+
17
+ # Provides the {Eth} module.
18
+ module Eth
19
+
20
+ # Provides a Ruby implementation of the Ethereum Application Binary Interface (ABI).
21
+ module Abi
22
+
23
+ # Provides a class to handle and parse common ABI types.
24
+ class Type
25
+
26
+ # Provides a specific parser error if type cannot be determined.
27
+ class ParseError < StandardError; end
28
+
29
+ # The base attribute, e.g., `string` or `bytes`.
30
+ attr :base_type
31
+
32
+ # The sub-type attribute, e.g., `256` as size of an uint256.
33
+ attr :sub_type
34
+
35
+ # The dimension attribute, e.g., `[10]` for an array of size 10.
36
+ attr :dimensions
37
+
38
+ # Create a new Type object for base types, sub types, and dimensions.
39
+ # Should not be used; use {Type.parse} instead.
40
+ #
41
+ # @param base_type [String] the base-type attribute.
42
+ # @param sub_type [String] the sub-type attribute.
43
+ # @param dimensions [Array] the dimension attribute.
44
+ # @return [Eth::Abi::Type] an ABI type object.
45
+ def initialize(base_type, sub_type, dimensions)
46
+ sub_type = sub_type.to_s
47
+ @base_type = base_type
48
+ @sub_type = sub_type
49
+ @dimensions = dimensions
50
+ end
51
+
52
+ # Converts the self.parse method into a constructor.
53
+ konstructor :parse
54
+
55
+ # Attempts to parse a string containing a common Solidity type.
56
+ # Creates a new Type upon success (using konstructor).
57
+ #
58
+ # @param type [String] a common Solidity type.
59
+ # @return [Eth::Abi::Type] a parsed Type object.
60
+ # @raise [ParseError] if it fails to parse the type.
61
+ def parse(type)
62
+ _, base_type, sub_type, dimension = /([a-z]*)([0-9]*x?[0-9]*)((\[[0-9]*\])*)/.match(type).to_a
63
+
64
+ # type dimension can only be numeric
65
+ dims = dimension.scan(/\[[0-9]*\]/)
66
+ raise ParseError, "Unknown characters found in array declaration" if dims.join != dimension
67
+
68
+ # enforce base types
69
+ validate_base_type base_type, sub_type
70
+
71
+ # return a new Type (using konstructor)
72
+ sub_type = sub_type.to_s
73
+ @base_type = base_type
74
+ @sub_type = sub_type
75
+ @dimensions = dims.map { |x| x[1...-1].to_i }
76
+ end
77
+
78
+ # Creates a new uint256 type used for size.
79
+ #
80
+ # @return [Eth::Abi::Type] a uint256 size type.
81
+ def self.size_type
82
+ @size_type ||= new("uint", 256, [])
83
+ end
84
+
85
+ # Compares two types for their attributes.
86
+ #
87
+ # @param another_type [Eth::Abi::Type] another type to be compared.
88
+ # @return [Boolean] true if all attributes match.
89
+ def ==(another_type)
90
+ base_type == another_type.base_type and
91
+ sub_type == another_type.sub_type and
92
+ dimensions == another_type.dimensions
93
+ end
94
+
95
+ # Computes the size of a type if possible.
96
+ #
97
+ # @return [Integer] the size of the type; or nil if not available.
98
+ def size
99
+ s = nil
100
+ if dimensions.empty?
101
+ unless ["string", "bytes"].include?(base_type) and sub_type.empty?
102
+ s = 32
103
+ end
104
+ else
105
+ unless dimensions.last == 0
106
+ unless nested_sub.is_dynamic?
107
+ s = dimensions.last * nested_sub.size
108
+ end
109
+ end
110
+ end
111
+ @size ||= s
112
+ end
113
+
114
+ # Helpes to determine whether array is of dynamic size.
115
+ #
116
+ # @return [Boolean] true if array is of dynamic size.
117
+ def is_dynamic?
118
+ size.nil?
119
+ end
120
+
121
+ # Types can have nested sub-types in arrays.
122
+ #
123
+ # @return [Eth::Abi::Type] nested sub-type.
124
+ def nested_sub
125
+ @nested_sub ||= self.class.new(base_type, sub_type, dimensions[0...-1])
126
+ end
127
+
128
+ private
129
+
130
+ # Validates all known base types and raises if an issue occurs.
131
+ def validate_base_type(base_type, sub_type)
132
+ case base_type
133
+ when "string"
134
+
135
+ # string can not have any suffix
136
+ raise ParseError, "String type must have no suffix or numerical suffix" unless sub_type.empty?
137
+ when "bytes"
138
+
139
+ # bytes can be no longer than 32 bytes
140
+ raise ParseError, "Maximum 32 bytes for fixed-length string or bytes" unless sub_type.empty? || sub_type.to_i <= 32
141
+ when "uint", "int"
142
+
143
+ # integers must have a numerical suffix
144
+ raise ParseError, "Integer type must have numerical suffix" unless sub_type =~ /\A[0-9]+\z/
145
+
146
+ # integer size must be valid
147
+ size = sub_type.to_i
148
+ raise ParseError, "Integer size out of bounds" unless size >= 8 && size <= 256
149
+ raise ParseError, "Integer size must be multiple of 8" unless size % 8 == 0
150
+ when "ureal", "real", "fixed", "ufixed"
151
+
152
+ # floats must have valid dimensional suffix
153
+ raise ParseError, "Real type must have suffix of form <high>x<low>, e.g. 128x128" unless sub_type =~ /\A[0-9]+x[0-9]+\z/
154
+ high, low = sub_type.split("x").map(&:to_i)
155
+ total = high + low
156
+ raise ParseError, "Real size out of bounds (max 32 bytes)" unless total >= 8 && total <= 256
157
+ raise ParseError, "Real high/low sizes must be multiples of 8" unless high % 8 == 0 && low % 8 == 0
158
+ when "hash"
159
+
160
+ # hashs must have numerical suffix
161
+ raise ParseError, "Hash type must have numerical suffix" unless sub_type =~ /\A[0-9]+\z/
162
+ when "address"
163
+
164
+ # addresses cannot have any suffix
165
+ raise ParseError, "Address cannot have suffix" unless sub_type.empty?
166
+ when "bool"
167
+
168
+ # booleans cannot have any suffix
169
+ raise ParseError, "Bool cannot have suffix" unless sub_type.empty?
170
+ else
171
+
172
+ # we cannot parse arbitrary types such as 'decimal' or 'hex'
173
+ raise ParseError, "Unknown base type"
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end