trx 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: dfcdbe41de11ca908dfaf1b12e58262dba9966cc7b319d57fc48c9e455d36360
4
+ data.tar.gz: f048ec52470a044ae883262dbfe51ee706bd2a8339a2298c014c642ac4e92e53
5
+ SHA512:
6
+ metadata.gz: 870645d6c67d40a2ca3eb7f6d70186408cfd622534eb89040008683298e68ae4c84a9137f6144771afe9003844b6fb3d7339fbb0eb1085f8c9c3835464ed54cc
7
+ data.tar.gz: 134d7401cfd15c6192f6f8974dd3fb13bf829e7e707632dba50166ecc26a422fe081a94b2cfccc78d37c749cc90293bc08abc50d3b07c9ce51a8fa2a8dc83408
@@ -0,0 +1,25 @@
1
+ module Trx
2
+ module Abi
3
+ class ContractEvent
4
+
5
+ attr_accessor :name, :signature, :input_types, :inputs, :event_string, :address, :client
6
+
7
+ def initialize(data)
8
+ @name = data["name"]
9
+ @input_types = data.fetch("inputs", []).map {|x| x["type"]}
10
+ @inputs = data.fetch("inputs", []).map {|x| x["name"]}
11
+ @event_string = "#{@name}(#{@input_types.join(",")})"
12
+ @signature = Digest::Keccak.hexdigest(@event_string, 256)
13
+ end
14
+
15
+ def set_address(address)
16
+ @address = address
17
+ end
18
+
19
+ def set_client(client)
20
+ @client = client
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,101 @@
1
+ module Trx
2
+ module Abi
3
+ class Decoder
4
+
5
+ def decode(type, value, start = 0)
6
+ is_array, arity, array_subtype = Abi::parse_array_type(type)
7
+ if is_array && arity
8
+ decode_static_array(arity, array_subtype, value, start)
9
+ elsif is_array
10
+ decode_dynamic_array(array_subtype, value, start)
11
+ else
12
+ value = value.gsub(/^0x/,'')
13
+ core, subtype = Abi::parse_type(type)
14
+ method_name = "decode_#{core}".to_sym
15
+ self.send(method_name, value, subtype, start)
16
+ end
17
+ end
18
+
19
+ def decode_static_array(arity, array_subtype, value, start)
20
+ (0..arity-1).map { |i| decode(array_subtype, value, start + i * 64) }
21
+ end
22
+
23
+ def decode_dynamic_array(array_subtype, value, start)
24
+ location = decode_uint(value[start..(start+63)]) * 2
25
+ size = decode_uint(value[location..location+63])
26
+ (0..size-1).map { |i| decode(array_subtype, value, location + (i+1) * 64) }
27
+ end
28
+
29
+ def decode_fixed(value, subtype = "128x128", start = 0)
30
+ decode_int(trim(value, start, fixed_bitsize(subtype))).to_f / 2**exponent(subtype)
31
+ end
32
+
33
+ def decode_uint(value, subtype = "256", start = 0)
34
+ trim(value, start, bitsize(subtype)).hex
35
+ end
36
+
37
+ def decode_int(value, subtype = "256", start = 0)
38
+ raise ArgumentError if value.nil?
39
+ size = bitsize(subtype)
40
+ value = trim(value, start, size)
41
+ (value[0..1] == "ff") ? (value.hex - (2 ** size)) : value.hex
42
+ end
43
+
44
+ def decode_bool(value, _, start)
45
+ value = trim(value, start, 4)
46
+ return true if value == "1"
47
+ return false if value == "0"
48
+ raise ArgumentError
49
+ end
50
+
51
+ def decode_address(value, _ = nil, start)
52
+ raise ArgumentError if value.size-start < 64
53
+ value[start+24..start+63]
54
+ end
55
+
56
+ def decode_bytes(value, subtype, start)
57
+ subtype.present? ? decode_static_bytes(value, subtype, start) : decode_dynamic_bytes(value, start)
58
+ end
59
+
60
+ def decode_static_bytes(value, subtype = nil, start = 0)
61
+ trim(value, start, subtype.to_i*8).scan(/.{2}/).map {|x| x.hex}.pack('C*').strip
62
+ end
63
+
64
+ def decode_dynamic_bytes(value, start = 0)
65
+ location = decode_uint(value[start..(start+63)]) * 2
66
+ size = decode_uint(value[location..location+63]) * 2
67
+ value[location+64..location+63+size].scan(/.{2}/).map {|x| x.hex}.pack('C*')
68
+ end
69
+
70
+ def decode_string(value, _ = nil, start = 0)
71
+ decode_dynamic_bytes(value, start).force_encoding('utf-8')
72
+ end
73
+
74
+ def decode_arguments(arguments, data)
75
+ data = data.gsub(/^0x/,'')
76
+ types = arguments.map { |o| o.type }
77
+ types.each.with_index.map { |t , i| decode(t, data, i*64) }
78
+ end
79
+
80
+ private
81
+ def trim(value, start, bitsize = 256)
82
+ value[start+63-(bitsize/4-1)..start+63]
83
+ end
84
+
85
+ def bitsize(subtype, default = 256)
86
+ subtype.present? ? subtype.to_i : default
87
+ end
88
+
89
+ def fixed_bitsize(subtype = nil)
90
+ subtype ||= "128x128"
91
+ _, x, n = /(\d+)x(\d+)/.match(subtype).to_a
92
+ x.to_i + n.to_i
93
+ end
94
+
95
+ def exponent(subtype, default = 128)
96
+ subtype.nil? ? default : /(\d+)x(\d+)/.match(subtype)[2].to_i
97
+ end
98
+
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,119 @@
1
+ module Trx
2
+
3
+ module Abi
4
+ class Encoder
5
+
6
+ def encode(type, value)
7
+ is_array, arity, array_subtype = Abi::parse_array_type(type)
8
+ if is_array && arity
9
+ encode_static_array(arity, array_subtype, value)
10
+ elsif is_array
11
+ encode_dynamic_array(array_subtype, value)
12
+ else
13
+ core, subtype = Abi::parse_type(type)
14
+ method_name = "encode_#{core}".to_sym
15
+ self.send(method_name, value, subtype)
16
+ end
17
+ end
18
+
19
+ def encode_static_array(arity, array_subtype, array)
20
+ raise "Wrong number of arguments" if arity != array.size
21
+ array.inject("") { |a, e| a << encode(array_subtype, e) }
22
+ end
23
+
24
+ def encode_dynamic_array(array_subtype, array)
25
+ location = encode_uint(@inputs ? size_of_inputs(@inputs) + @tail.size/2 : 32)
26
+ size = encode_uint(array.size)
27
+ data = array.inject("") { |a, e| a << encode(array_subtype, e) }
28
+ [location, size + data]
29
+ end
30
+
31
+ def encode_int(value, _ = nil)
32
+ to_twos_complement(value).to_s(16).rjust(64, '0')
33
+ end
34
+
35
+ def encode_uint(value, _ = nil)
36
+ raise ArgumentError if value < 0
37
+ encode_int(value)
38
+ end
39
+
40
+ def encode_bool(value, _)
41
+ (value ? "1" : "0").rjust(64, '0')
42
+ end
43
+
44
+ def encode_fixed(value, subtype)
45
+ n = subtype.nil? ? 128 : /(\d+)x(\d+)/.match(subtype)[2].to_i
46
+ do_encode_fixed(value, n)
47
+ end
48
+
49
+ def do_encode_fixed(value, n)
50
+ encode_uint((value * 2**n).to_i)
51
+ end
52
+
53
+ def encode_ufixed(_value, _)
54
+ raise NotImplementedError
55
+ end
56
+
57
+ def encode_bytes(value, subtype)
58
+ subtype.nil? ? encode_dynamic_bytes(value) : encode_static_bytes(value)
59
+ end
60
+
61
+ def encode_static_bytes(value)
62
+ value.bytes.map {|x| x.to_s(16).rjust(2, '0')}.join("").ljust(64, '0')
63
+ end
64
+
65
+ def encode_dynamic_bytes(value)
66
+ location = encode_uint(@inputs ? size_of_inputs(@inputs) + @tail.size/2 : 32)
67
+ size = encode_uint(value.size)
68
+ content = encode_static_bytes(value)
69
+ [location, size + content]
70
+ end
71
+
72
+ def encode_string(value, _)
73
+ location = encode_uint(@inputs ? size_of_inputs(@inputs) + @tail.size/2 : 32)
74
+ size = encode_uint(value.bytes.size)
75
+ content = value.bytes.map {|x| x.to_s(16).rjust(2, '0')}.join("").ljust(64, '0')
76
+ [location, size + content]
77
+ end
78
+
79
+ def encode_address(value, _)
80
+ value = "0" * 24 + value.gsub(/^0x/,'')
81
+ raise ArgumentError if value.size != 64
82
+ value
83
+ end
84
+
85
+ def ensure_prefix(value)
86
+ value.start_with?("0x") ? value : ("0x" + value)
87
+ end
88
+
89
+ def encode_arguments(inputs, args)
90
+ raise "Wrong number of arguments" if inputs.length != args.length
91
+ @head = ""
92
+ @tail = ""
93
+ @inputs = inputs
94
+ inputs.each.with_index do |input, index|
95
+ encoded = encode(input.type, args[index])
96
+ if encoded.is_a? Array
97
+ @head << encoded[0]
98
+ @tail << encoded[1]
99
+ else
100
+ @head << encoded
101
+ end
102
+ end
103
+ @head + @tail
104
+ end
105
+
106
+ private
107
+ def to_twos_complement(number)
108
+ (number & ((1 << 256) - 1))
109
+ end
110
+
111
+ def size_of_inputs(inputs)
112
+ inputs.map do |input|
113
+ _, arity, _ = Abi::parse_array_type(input.type)
114
+ arity.nil? ? 32 : arity * 32
115
+ end.inject(:+)
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,37 @@
1
+ module Trx
2
+ module Abi
3
+ class Function
4
+
5
+ attr_accessor :name, :inputs, :outputs, :signature, :constant, :function_string
6
+
7
+ def initialize(data)
8
+ @name = data["name"]
9
+ @constant = data["constant"]
10
+ @inputs = data.fetch("inputs", []).map do |input|
11
+ FunctionInput.new(input)
12
+ end
13
+ @outputs = data.fetch("outputs", []).map do |output|
14
+ FunctionOutput.new(output)
15
+ end
16
+ @function_string = self.class.calc_signature(@name, @inputs)
17
+ @signature = self.class.calc_id(@function_string)
18
+ end
19
+
20
+ def self.to_canonical_type(type)
21
+ type
22
+ .gsub(/(int)(\z|\D)/, '\1256\2')
23
+ .gsub(/(uint)(\z|\D)/, '\1256\2')
24
+ .gsub(/(fixed)(\z|\D)/, '\1128x128\2')
25
+ .gsub(/(ufixed)(\z|\D)/, '\1128x128\2')
26
+ end
27
+
28
+ def self.calc_signature(name, inputs)
29
+ "#{name}(#{inputs.map {|x| self.to_canonical_type(x.type) }.join(",")})"
30
+ end
31
+
32
+ def self.calc_id(signature)
33
+ Digest::Keccak.hexdigest(signature, 256)[0..7]
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ module Trx
2
+
3
+ module Abi
4
+ class FunctionInput
5
+
6
+ attr_accessor :type, :name
7
+
8
+ def initialize(data)
9
+ @type = data["type"]
10
+ @name = data["name"]
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Trx
2
+
3
+ module Abi
4
+ class FunctionOutput
5
+
6
+ attr_accessor :type, :name
7
+
8
+ def initialize(data)
9
+ @type = data["type"]
10
+ @name = data["name"]
11
+ end
12
+
13
+ end
14
+ end
15
+ end
data/lib/trx/abi.rb ADDED
@@ -0,0 +1,33 @@
1
+ module Trx
2
+ module Abi
3
+ extend self
4
+
5
+ def parse_abi(abi)
6
+ constructor = abi.detect {|x| x["type"].downcase == "constructor"}
7
+ if constructor.present?
8
+ constructor_inputs = constructor["inputs"].map { |input| FunctionInput.new(input) }
9
+ else
10
+ constructor_inputs = []
11
+ end
12
+ functions = abi.select {|x| x["type"].downcase == "function" }.map { |fun| Function.new(fun) }
13
+ events = abi.select {|x| x["type"].downcase == "event" }.map { |evt| ContractEvent.new(evt) }
14
+ [constructor_inputs, functions, events]
15
+ end
16
+
17
+ def parse_type(type)
18
+ raise NotImplementedError if type.ends_with?("]")
19
+ match = /(\D+)(\d.*)?/.match(type)
20
+ [match[1], match[2]]
21
+ end
22
+
23
+ def parse_array_type(type)
24
+ match = /(.+)\[(\d*)\]\z/.match(type)
25
+ if match
26
+ [true, match[2].present? ? match[2].to_i : nil, match[1]]
27
+ else
28
+ [false, nil, nil]
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trx
4
+ class Address
5
+ ADDRESS_PREFIX = "41"
6
+
7
+ def self.from_public_hex(public_hex)
8
+ raise ArgumentError, "Expected String, got #{public_hex.class}" unless public_hex.is_a?(String)
9
+
10
+ bytes = Utils.hex_to_bin(public_hex)
11
+ address_bytes = Utils.keccak256(bytes[1..-1])[-20..-1]
12
+ prefixed_address_hex = ADDRESS_PREFIX + RLP::Utils.encode_hex(address_bytes)
13
+ prefixed_address_bytes = Utils.hex_to_bin(prefixed_address_hex)
14
+ checksum = Utils.base58check(prefixed_address_bytes).hexdigest[0..7]
15
+ base58check_adress = Base58.encode_hex(prefixed_address_hex + checksum)
16
+
17
+ Address.new(base58check_adress)
18
+ end
19
+
20
+ attr_reader :address
21
+
22
+ def initialize(address)
23
+ raise ArgumentError, "Expected String, got #{address.class}" unless address.is_a?(String)
24
+
25
+ @address = Utils.prefix_hex(address)
26
+ end
27
+
28
+ def checksum_matches?
29
+ computed_checksum = Utils.sha256(
30
+ Utils.sha256(to_bytes).digest
31
+ ).hexdigest[0..7]
32
+
33
+ checksum_hex == computed_checksum
34
+ end
35
+ alias_method :valid?, :checksum_matches?
36
+
37
+ def to_bytes
38
+ Utils.hex_to_bin(to_base58_decode_hex)[0..-5]
39
+ end
40
+
41
+ def to_base58_decode_hex
42
+ Utils.base58_decode_hex(address)
43
+ end
44
+
45
+ def to_hex
46
+ Utils.base58_decode_hex(address)[0..-9]
47
+ end
48
+
49
+ def to_s
50
+ Utils.remove_hex_prefix(address)
51
+ end
52
+
53
+ private
54
+
55
+ def checksum_bytes
56
+ bytes[0..3]
57
+ end
58
+
59
+ def checksum_hex
60
+ to_base58_decode_hex[-8..-1]
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,34 @@
1
+ module Trx
2
+ class HttpClient
3
+ attr_reader :host, :timeout, :trongrig_token, :headers, :raise_error
4
+
5
+ MAINNET_HOST = "https://api.trongrid.io"
6
+ SHASTA_HOST = "https://api.shasta.trongrid.io"
7
+ NILE_HOST = "https://nile.trongrid.io"
8
+
9
+ def initialize(host = nil, timeout: 10, trongrig_token: nil, headers: {}, raise_error: true)
10
+ @host = host
11
+ @timeout = timeout
12
+ @trongrig_token = trongrig_token
13
+ @headers = headers
14
+ @raise_error = raise_error
15
+ end
16
+
17
+ def perform_command(command, params, method: :post)
18
+ connection.public_send(method, command, params).body
19
+ end
20
+
21
+ private
22
+
23
+ def connection
24
+ @_connection ||= Faraday.new(host) do |builder|
25
+ builder.options.timeout = timeout
26
+ builder.use Faraday::Response::RaiseError if raise_error
27
+ builder.request :url_encoded
28
+ builder.response :json
29
+ builder.adapter Faraday.default_adapter
30
+ builder.headers['TRON-PRO-API-KEY'] = trongrig_token unless trongrig_token.nil?
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/trx/key.rb ADDED
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trx
4
+ class Key
5
+ attr_reader :private_key, :public_key
6
+
7
+ def initialize(priv: nil)
8
+
9
+ # Creates a new, randomized libsecp256k1 context.
10
+ ctx = Secp256k1::Context.new context_randomization_bytes: SecureRandom.random_bytes(32)
11
+
12
+ key = if priv.nil?
13
+ # Creates a new random key pair (public, private).
14
+ ctx.generate_key_pair
15
+ else
16
+
17
+ # Converts hex private keys to binary strings.
18
+ priv = Utils.hex_to_bin priv if Utils.is_hex? priv
19
+
20
+ # Creates a keypair from existing private key data.
21
+ ctx.key_pair_from_private_key priv
22
+ end
23
+
24
+ # Sets the attributes.
25
+ @private_key = key.private_key
26
+ @public_key = key.public_key
27
+ end
28
+
29
+ def private_hex
30
+ Utils.bin_to_hex @private_key.data
31
+ end
32
+
33
+ def private_bytes
34
+ @private_key.data
35
+ end
36
+
37
+ def public_hex
38
+ Utils.bin_to_hex @public_key.uncompressed
39
+ end
40
+
41
+ def public_hex_compressed
42
+ Utils.bin_to_hex @public_key.compressed
43
+ end
44
+
45
+ def public_bytes
46
+ @public_key.uncompressed
47
+ end
48
+
49
+ def public_bytes_compressed
50
+ @public_key.compressed
51
+ end
52
+
53
+ def address
54
+ Address.from_public_hex public_hex
55
+ end
56
+
57
+ def sign(blob)
58
+ context = Secp256k1::Context.new
59
+ compact, recovery_id = context.sign_recoverable(@private_key, blob).compact
60
+ signature = compact.bytes
61
+ is_leading_zero = true
62
+ signature.append recovery_id
63
+
64
+ # TODO: WTF? It is necessary?
65
+
66
+ # [recovery_id].pack("N").unpack("C*").each do |byte|
67
+ # is_leading_zero = false if byte > 0 and is_leading_zero
68
+ # unless is_leading_zero and byte === 0
69
+ # signature.append recovery_id
70
+ # end
71
+ # end
72
+
73
+ Utils.bin_to_hex signature.pack "c*"
74
+ end
75
+
76
+ def personal_sign(message)
77
+ prefixed_message = Signature.prefix_message message
78
+ hashed_message = Utils.keccak256 prefixed_message
79
+ sign hashed_message
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trx
4
+ module Signature
5
+ class SignatureError < StandardError; end
6
+ extend self
7
+
8
+ PREFIX_BYTE = "\x19".freeze
9
+
10
+ def prefix_message(message)
11
+ "#{PREFIX_BYTE}Tron Signed Message:\n#{message.size}#{message}"
12
+ end
13
+ end
14
+ end
data/lib/trx/utils.rb ADDED
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trx
4
+ module Utils
5
+ extend self
6
+
7
+ def hex_to_bin(string)
8
+ RLP::Utils.decode_hex remove_hex_prefix(string)
9
+ end
10
+
11
+ def bin_to_hex(bytes)
12
+ RLP::Utils.encode_hex bytes
13
+ end
14
+
15
+ def remove_hex_prefix(string)
16
+ string[0, 2] == "0x" ? string[2..-1] : string
17
+ end
18
+
19
+ def prefix_hex(hex)
20
+ hex.match(/\A0x/) ? hex : "0x#{hex}"
21
+ end
22
+
23
+ def keccak256(value)
24
+ Digest::Keccak.new(256).digest(value)
25
+ end
26
+
27
+ def base58check(value)
28
+ sha256(sha256(value).digest)
29
+ end
30
+
31
+ def base58_decode_hex(hex)
32
+ Base58.decode_hex(remove_hex_prefix(hex))
33
+ end
34
+
35
+ def sha256(value)
36
+ hash = OpenSSL::Digest.new("SHA256")
37
+ hash.update(value)
38
+
39
+ hash
40
+ end
41
+
42
+ def is_hex?(str)
43
+ return false unless str.is_a? String
44
+ str = remove_hex_prefix str
45
+ str.match /\A[0-9a-fA-F]*\z/
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trx
4
+ VERSION = "0.2.2"
5
+ end
data/lib/trx.rb ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/keccak"
4
+ require "rlp"
5
+ require "openssl"
6
+ require "base58-alphabets"
7
+ require "rbsecp256k1"
8
+ require "securerandom"
9
+ require "faraday"
10
+ require "active_support"
11
+ require "active_support/core_ext"
12
+
13
+ require_relative "trx/utils"
14
+ require_relative "trx/signature"
15
+ require_relative "trx/key"
16
+ require_relative "trx/address"
17
+ require_relative "trx/version"
18
+ require_relative "trx/http_client"
19
+ require_relative "trx/abi"
20
+ require_relative "trx/abi/encoder"
21
+ require_relative "trx/abi/decoder"
22
+ require_relative "trx/abi/function"
23
+ require_relative "trx/abi/function_input"
24
+ require_relative "trx/abi/function_output"
25
+ require_relative "trx/abi/contract_event"
26
+
27
+ module Trx
28
+ class Error < StandardError; end
29
+ end
metadata ADDED
@@ -0,0 +1,201 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - Anton Kostyuk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-02-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.2'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ecdsa
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: faraday
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.2.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.2.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: keccak
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.3.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.3.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: rlp
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.7.3
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.7.3
97
+ - !ruby/object:Gem::Dependency
98
+ name: rbsecp256k1
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '5.1'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '5.1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: securerandom
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: base58-alphabets
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: activesupport
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '4.2'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '4.2'
153
+ description: ''
154
+ email:
155
+ - anton.kostuk.2012@gmail.com
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - lib/trx.rb
161
+ - lib/trx/abi.rb
162
+ - lib/trx/abi/contract_event.rb
163
+ - lib/trx/abi/decoder.rb
164
+ - lib/trx/abi/encoder.rb
165
+ - lib/trx/abi/function.rb
166
+ - lib/trx/abi/function_input.rb
167
+ - lib/trx/abi/function_output.rb
168
+ - lib/trx/address.rb
169
+ - lib/trx/http_client.rb
170
+ - lib/trx/key.rb
171
+ - lib/trx/signature.rb
172
+ - lib/trx/utils.rb
173
+ - lib/trx/version.rb
174
+ homepage: https://github.com/RainbowPonny/trx-rb
175
+ licenses:
176
+ - MIT
177
+ metadata:
178
+ homepage_uri: https://github.com/RainbowPonny/trx-rb
179
+ source_code_uri: https://github.com/RainbowPonny/trx-rb
180
+ changelog_uri: https://github.com/RainbowPonny/trx-rb
181
+ rubygems_mfa_required: 'true'
182
+ post_install_message:
183
+ rdoc_options: []
184
+ require_paths:
185
+ - lib
186
+ required_ruby_version: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ version: 2.5.0
191
+ required_rubygems_version: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ requirements: []
197
+ rubygems_version: 3.3.7
198
+ signing_key:
199
+ specification_version: 4
200
+ summary: TRON HTTP API client
201
+ test_files: []