tron.rb 1.1.2 → 1.1.4

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.
@@ -1,38 +1,91 @@
1
1
  # lib/tron/utils/address.rb
2
- require 'base58'
2
+ require 'base58-alphabets'
3
3
 
4
4
  module Tron
5
5
  module Utils
6
+ # TRON address utilities for validation, conversion, and formatting
6
7
  class Address
8
+ # TRON address prefix in hex (41 corresponds to 'T' in Base58)
9
+ ADDRESS_PREFIX = '41'.freeze
10
+
11
+ # Validates a TRON address
12
+ #
13
+ # @param address [String] the TRON address to validate
14
+ # @return [Boolean] true if the address is valid, false otherwise
7
15
  def self.validate(address)
8
16
  return false unless address && address.length == 34 && address.start_with?('T')
9
17
 
10
18
  begin
11
- base58_part = address[1..-1]
12
- Base58.decode(base58_part)
13
- true
19
+ # Decode the entire Base58 address to get the raw bytes
20
+ decoded_bytes = Base58.decode_bin(address)
21
+ # Should have 21 bytes (1 byte prefix + 20 address bytes) + 4 bytes checksum = 25 bytes total
22
+ return false unless decoded_bytes.length == 25
23
+
24
+ # Split into address part (21 bytes) and checksum (4 bytes)
25
+ addr_part = decoded_bytes[0...21]
26
+ checksum = decoded_bytes[21..-1]
27
+
28
+ # Verify the checksum by double-SHA256 of the address part
29
+ require 'digest'
30
+ expected_checksum = Digest::SHA256.digest(Digest::SHA256.digest(addr_part))[0...4]
31
+
32
+ # Check if the address prefix is correct (should be 0x41 which is decimal 65)
33
+ return (checksum == expected_checksum) && (addr_part[0].ord == 65) # 0x41 = 65 in decimal
14
34
  rescue
15
35
  false
16
36
  end
17
37
  end
18
38
 
39
+ # Converts a Base58 TRON address to hex format
40
+ #
41
+ # @param address [String] the Base58 TRON address to convert
42
+ # @return [String] the address in hex format
43
+ # @raise [ArgumentError] if the address is invalid
19
44
  def self.to_hex(address)
20
- return address if address.start_with?('41') && address.length == 42 # Already hex format
45
+ return address if address.start_with?(ADDRESS_PREFIX) && address.length == 42 # Already hex format
21
46
 
22
- base58_part = address.start_with?('T') ? address[1..-1] : address
23
- decoded = Base58.decode(base58_part)
24
- '41' + decoded.unpack('H*').first
47
+ # Decode the full Base58 address to get the raw bytes
48
+ decoded_bytes = Base58.decode_bin(address)
49
+ # Should have 21 bytes (1 byte prefix + 20 address bytes) + 4 bytes checksum = 25 bytes total
50
+ raise ArgumentError, "Invalid TRON address format: #{address}" unless decoded_bytes.length == 25
51
+
52
+ # Take only the first 21 bytes (address part with prefix)
53
+ addr_part = decoded_bytes[0...21]
54
+
55
+ # Convert to hex string
56
+ addr_part.unpack1('H*')
57
+ end
58
+
59
+ # Converts a hex address to Base58 format
60
+ #
61
+ # @param hex_address [String] the hex address to convert
62
+ # @return [String] the address in Base58 format
63
+ def self.from_hex(hex_address)
64
+ to_base58(hex_address)
25
65
  end
26
66
 
67
+ # Converts a hex address to Base58 format
68
+ #
69
+ # @param hex_address [String] the hex address to convert
70
+ # @return [String] the address in Base58 format
27
71
  def self.to_base58(hex_address)
28
72
  return hex_address if hex_address.start_with?('T') && hex_address.length == 34 # Already base58 format
29
73
 
30
- hex_without_prefix = hex_address.start_with?('41') ? hex_address[2..-1] : hex_address
74
+ hex_without_prefix = hex_address.start_with?(ADDRESS_PREFIX) ? hex_address[2..-1] : hex_address
31
75
  address_bytes = [hex_without_prefix].pack('H*')
32
76
 
77
+ # Verify the address part is correct length (21 bytes after including prefix)
78
+ if address_bytes.length != 21
79
+ # Add the prefix byte 0x41 (decimal 65) if not present
80
+ address_bytes = [65].pack('C') + address_bytes if address_bytes.length == 20
81
+ end
82
+
33
83
  require 'digest'
34
84
  checksum = Digest::SHA256.digest(Digest::SHA256.digest(address_bytes))[0...4]
35
- Base58.binary_to_base58(address_bytes + checksum)
85
+ full_bytes = address_bytes + checksum
86
+
87
+ # Encode to Base58
88
+ Base58.encode_bin(full_bytes)
36
89
  end
37
90
  end
38
91
  end
@@ -3,9 +3,13 @@ require 'monitor'
3
3
 
4
4
  module Tron
5
5
  module Utils
6
+ # A simple thread-safe cache with time-based expiration
6
7
  class Cache
7
8
  include MonitorMixin
8
9
 
10
+ # Creates a new cache instance with the specified maximum age
11
+ #
12
+ # @param max_age [Integer] maximum age of cached entries in seconds (default: 300)
9
13
  def initialize(max_age: 300) # 5 minutes default
10
14
  super()
11
15
  @cache = {}
@@ -13,6 +17,11 @@ module Tron
13
17
  @max_age = max_age
14
18
  end
15
19
 
20
+ # Retrieves a value from the cache
21
+ # Automatically removes expired entries before retrieval
22
+ #
23
+ # @param key [Object] the cache key
24
+ # @return [Object, nil] the cached value or nil if not found or expired
16
25
  def get(key)
17
26
  synchronize do
18
27
  cleanup_expired_entries
@@ -25,6 +34,10 @@ module Tron
25
34
  end
26
35
  end
27
36
 
37
+ # Sets a value in the cache with the current timestamp
38
+ #
39
+ # @param key [Object] the cache key
40
+ # @param value [Object] the value to cache
28
41
  def set(key, value)
29
42
  synchronize do
30
43
  @cache[key] = value
@@ -32,6 +45,9 @@ module Tron
32
45
  end
33
46
  end
34
47
 
48
+ # Removes a specific key from the cache
49
+ #
50
+ # @param key [Object] the cache key to delete
35
51
  def delete(key)
36
52
  synchronize do
37
53
  @cache.delete(key)
@@ -39,6 +55,7 @@ module Tron
39
55
  end
40
56
  end
41
57
 
58
+ # Clears all entries from the cache
42
59
  def clear
43
60
  synchronize do
44
61
  @cache.clear
@@ -48,6 +65,7 @@ module Tron
48
65
 
49
66
  private
50
67
 
68
+ # Removes expired entries from the cache
51
69
  def cleanup_expired_entries
52
70
  now = Time.now.to_f
53
71
  expired_keys = @timestamps.select { |_, timestamp| now - timestamp > @max_age }.keys
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ require 'digest/keccak'
3
+ require 'openssl'
4
+ require 'base58-alphabets'
5
+
6
+ module Tron
7
+ module Utils
8
+ # Crypto utilities for various cryptographic operations needed in TRON blockchain
9
+ module Crypto
10
+ extend self
11
+
12
+ # Converts a hexadecimal string to binary data
13
+ #
14
+ # @param string [String] the hex string to convert (with or without 0x prefix)
15
+ # @return [String] the binary representation
16
+ def hex_to_bin(string)
17
+ string = string[2..-1] if string.start_with?('0x', '0X')
18
+ [string].pack('H*')
19
+ end
20
+
21
+ # Converts binary data to a hexadecimal string
22
+ #
23
+ # @param bytes [String] the binary data to convert
24
+ # @return [String] the hexadecimal representation
25
+ def bin_to_hex(bytes)
26
+ bytes.unpack('H*').first
27
+ end
28
+
29
+ # Computes the Keccak256 hash of the given value
30
+ #
31
+ # @param value [String] the value to hash
32
+ # @return [String] the Keccak256 hash
33
+ def keccak256(value)
34
+ # Using keccak gem for Keccak256 hashing
35
+ Digest::Keccak.digest(value, 256)
36
+ end
37
+
38
+ # Computes the SHA256 hash of the given value
39
+ #
40
+ # @param value [String] the value to hash
41
+ # @return [String] the SHA256 hash
42
+ def sha256(value)
43
+ OpenSSL::Digest::SHA256.digest(value)
44
+ end
45
+
46
+ # Checks if a string is a valid hexadecimal string
47
+ #
48
+ # @param str [String] the string to check
49
+ # @return [Boolean] true if the string is valid hex, false otherwise
50
+ def is_hex?(str)
51
+ return false unless str.is_a?(String)
52
+ str = str[2..-1] if str.start_with?('0x', '0X')
53
+ str.match(/\A[0-9a-fA-F]*\z/)
54
+ end
55
+
56
+ # Applies Base58Check encoding to the given data
57
+ # This creates a checksum and encodes the data with the checksum
58
+ #
59
+ # @param data [String] the data to encode
60
+ # @return [String] the Base58Check encoded string
61
+ def base58check(data)
62
+ checksum = sha256(sha256(data))[0..3]
63
+ Base58.encode_bin(data + checksum)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -6,6 +6,7 @@ require 'digest'
6
6
 
7
7
  module Tron
8
8
  module Utils
9
+ # HTTP utility class that handles HTTP requests with caching and error handling
9
10
  class HTTP
10
11
  # TTL values for different endpoint types (in seconds)
11
12
  # These are optimized based on data volatility
@@ -26,7 +27,8 @@ module Tron
26
27
  default: { ttl: 300, max_stale: 600 }
27
28
  }.freeze
28
29
 
29
- # GET request with optional caching
30
+ # Makes a GET request with optional caching
31
+ #
30
32
  # @param url [String] the URL to request
31
33
  # @param headers [Hash] request headers
32
34
  # @param cache_options [Hash] optional cache configuration
@@ -34,6 +36,7 @@ module Tron
34
36
  # @option cache_options [Integer] :ttl custom TTL in seconds
35
37
  # @option cache_options [Integer] :max_stale custom max_stale in seconds
36
38
  # @option cache_options [Symbol] :endpoint_type endpoint type for TTL lookup
39
+ # @return [Hash, Array] the parsed JSON response
37
40
  def self.get(url, headers = {}, cache_options = {})
38
41
  if should_use_cache?(cache_options)
39
42
  cache_key = generate_cache_key('GET', url, headers)
@@ -47,12 +50,33 @@ module Tron
47
50
  end
48
51
  end
49
52
 
50
- # POST request (no caching for mutations)
51
- def self.post(url, body = nil, headers = {})
52
- make_request(Net::HTTP::Post, url, body, headers)
53
+ # Makes a POST request (no caching for mutations)
54
+ #
55
+ # @param url [String] the URL to request
56
+ # @param payload [Hash, String] the request payload
57
+ # @param cache_options [Hash] optional cache configuration (unused for POST)
58
+ # @return [Hash, Array] the parsed JSON response
59
+ def self.post(url, payload, cache_options = {})
60
+ require 'net/http'
61
+ require 'json'
62
+
63
+ uri = URI(url)
64
+ http = Net::HTTP.new(uri.host, uri.port)
65
+ http.use_ssl = (uri.scheme == 'https')
66
+
67
+ request = Net::HTTP::Post.new(uri.path, {
68
+ 'Content-Type' => 'application/json',
69
+ 'TRON-PRO-API-KEY' => Tron.configuration.api_key
70
+ }.compact)
71
+
72
+ request.body = payload.to_json
73
+
74
+ response = http.request(request)
75
+ JSON.parse(response.body)
53
76
  end
54
77
 
55
78
  # Clear cache for a specific endpoint
79
+ #
56
80
  # @param url [String] the URL to clear from cache
57
81
  # @param headers [Hash] request headers used in the original request
58
82
  def self.clear_cache(url, headers = {})
@@ -61,8 +85,10 @@ module Tron
61
85
  end
62
86
 
63
87
  # Get cache statistics for an endpoint
88
+ #
64
89
  # @param url [String] the URL to get stats for
65
90
  # @param headers [Hash] request headers used in the original request
91
+ # @return [Hash] cache statistics for the endpoint
66
92
  def self.cache_stats(url, headers = {})
67
93
  cache_key = generate_cache_key('GET', url, headers)
68
94
  Tron::Cache.stats(cache_key)
@@ -71,6 +97,9 @@ module Tron
71
97
  private
72
98
 
73
99
  # Determine if caching should be used for this request
100
+ #
101
+ # @param cache_options [Hash] the cache configuration options
102
+ # @return [Boolean] true if caching should be used
74
103
  def self.should_use_cache?(cache_options)
75
104
  # Check if caching is explicitly disabled for this request
76
105
  return false if cache_options[:enabled] == false
@@ -80,6 +109,9 @@ module Tron
80
109
  end
81
110
 
82
111
  # Get TTL configuration for the request
112
+ #
113
+ # @param cache_options [Hash] the cache configuration options
114
+ # @return [Hash] TTL configuration with :ttl and :max_stale values
83
115
  def self.get_ttl_config(cache_options)
84
116
  # If custom TTL provided, use it
85
117
  if cache_options[:ttl] && cache_options[:max_stale]
@@ -104,6 +136,11 @@ module Tron
104
136
  end
105
137
 
106
138
  # Generate a unique cache key based on request parameters
139
+ #
140
+ # @param method [String] the HTTP method
141
+ # @param url [String] the request URL
142
+ # @param headers [Hash] the request headers
143
+ # @return [String] the cache key
107
144
  def self.generate_cache_key(method, url, headers)
108
145
  # Include method, URL, and relevant headers in the cache key
109
146
  # Exclude headers that don't affect the response (like User-Agent)
@@ -112,6 +149,14 @@ module Tron
112
149
  Digest::SHA256.hexdigest(key_parts.to_json)
113
150
  end
114
151
 
152
+ # Makes an HTTP request
153
+ #
154
+ # @param method_class [Class] the HTTP method class (e.g. Net::HTTP::Get)
155
+ # @param url [String] the URL to request
156
+ # @param body [String] the request body
157
+ # @param headers [Hash] the request headers
158
+ # @return [Hash, Array] the parsed JSON response
159
+ # @raise [RuntimeError] if the request fails
115
160
  def self.make_request(method_class, url, body, headers)
116
161
  uri = URI(url)
117
162
  http = Net::HTTP.new(uri.host, uri.port)
@@ -3,9 +3,14 @@ require 'monitor'
3
3
 
4
4
  module Tron
5
5
  module Utils
6
+ # A thread-safe rate limiter that limits requests based on a maximum number of requests within a specific time window
6
7
  class RateLimiter
7
8
  include MonitorMixin
8
9
 
10
+ # Creates a new rate limiter instance
11
+ #
12
+ # @param max_requests [Integer] maximum number of requests allowed in the time window
13
+ # @param time_window [Float] time window in seconds
9
14
  def initialize(max_requests:, time_window:)
10
15
  super()
11
16
  @max_requests = max_requests
@@ -13,6 +18,9 @@ module Tron
13
18
  @request_timestamps = []
14
19
  end
15
20
 
21
+ # Checks if a request can be made without exceeding the rate limit
22
+ #
23
+ # @return [Boolean] true if a request can be made, false otherwise
16
24
  def can_make_request?
17
25
  synchronize do
18
26
  cleanup_old_requests
@@ -20,6 +28,10 @@ module Tron
20
28
  end
21
29
  end
22
30
 
31
+ # Executes a request, blocking if necessary to respect the rate limit
32
+ # This method will sleep if necessary to ensure the rate limit is not exceeded
33
+ #
34
+ # @return [Float] the time until the next request is allowed
23
35
  def execute_request
24
36
  synchronize do
25
37
  cleanup_old_requests
@@ -40,11 +52,15 @@ module Tron
40
52
 
41
53
  private
42
54
 
55
+ # Removes timestamps that are outside the time window
43
56
  def cleanup_old_requests
44
57
  now = Time.now.to_f
45
58
  @request_timestamps.reject! { |timestamp| now - timestamp > @time_window }
46
59
  end
47
60
 
61
+ # Calculates the time until the next request is allowed
62
+ #
63
+ # @return [Float] the time in seconds until the next request is allowed
48
64
  def calculate_time_to_next_request
49
65
  if @request_timestamps.length <= 1
50
66
  0
data/lib/tron/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  # lib/tron/version.rb
4
4
  module Tron
5
- VERSION = "1.1.2".freeze
5
+ VERSION = "1.1.4".freeze
6
6
  end
data/lib/tron.rb CHANGED
@@ -5,9 +5,20 @@ require_relative 'tron/version'
5
5
  require_relative 'tron/client'
6
6
  require_relative 'tron/configuration'
7
7
  require_relative 'tron/cache'
8
+ require_relative 'tron/key'
9
+ require_relative 'tron/signature'
10
+ require_relative 'tron/abi'
11
+ require_relative 'tron/contract'
12
+ require_relative 'tron/protobuf'
8
13
 
14
+ # The main module for the Tron Ruby Client
15
+ # This module provides a simplified interface to interact with the TRON blockchain
9
16
  module Tron
10
17
  class << self
18
+ # Returns the default client instance
19
+ # Creates a new instance if one doesn't exist
20
+ #
21
+ # @return [Tron::Client] the client instance
11
22
  def client
12
23
  @client ||= Client.new(
13
24
  api_key: Client.configuration.api_key,
@@ -17,16 +28,29 @@ module Tron
17
28
  )
18
29
  end
19
30
 
31
+ # Configures the default client
32
+ # Resets the client when configuration changes
33
+ #
34
+ # @yield [config] block to configure the client
35
+ # @yieldparam [Tron::Configuration] config the configuration object
20
36
  def configure(&block)
21
37
  @client = nil # Reset client when configuration changes
22
38
  Client.configure(&block)
23
39
  end
24
40
 
41
+ # Returns the current configuration
42
+ #
43
+ # @return [Tron::Configuration] the configuration object
25
44
  def configuration
26
45
  Client.configuration
27
46
  end
28
47
 
29
- # Delegate common methods to the default client
48
+ # Delegates common methods to the default client
49
+ #
50
+ # @param method [Symbol] the method to call
51
+ # @param args [Array] arguments to pass to the method
52
+ # @param block [Proc] block to pass to the method
53
+ # @return the result of the method call
30
54
  def method_missing(method, *args, &block)
31
55
  if client.respond_to?(method)
32
56
  client.send(method, *args, &block)
@@ -35,6 +59,11 @@ module Tron
35
59
  end
36
60
  end
37
61
 
62
+ # Checks if the module responds to a method
63
+ #
64
+ # @param method [Symbol] the method to check
65
+ # @param include_private [Boolean] whether to include private methods
66
+ # @return [Boolean] true if the module responds to the method
38
67
  def respond_to_missing?(method, include_private = false)
39
68
  client.respond_to?(method) || super
40
69
  end
metadata CHANGED
@@ -1,43 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tron.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
- - Your Name
7
+ - Bolo Michelin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-24 00:00:00.000000000 Z
11
+ date: 2025-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: base58
14
+ name: base58-alphabets
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.2'
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.2'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: dotenv
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.7'
33
+ version: '2.8'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.7'
40
+ version: '2.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: keccak
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rbsecp256k1
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '6.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '6.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: google-protobuf
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.22'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.22'
41
83
  - !ruby/object:Gem::Dependency
42
84
  name: bundler
43
85
  requirement: !ruby/object:Gem::Requirement
@@ -83,7 +125,7 @@ dependencies:
83
125
  description: A Ruby gem for interacting with TRON blockchain APIs, including balance
84
126
  checking, resource information, and token prices.
85
127
  email:
86
- - your.email@example.com
128
+ - bolo@scionx.io
87
129
  executables:
88
130
  - tron-wallet
89
131
  extensions: []
@@ -93,18 +135,35 @@ files:
93
135
  - README.md
94
136
  - bin/tron-wallet
95
137
  - lib/tron.rb
138
+ - lib/tron/abi.rb
139
+ - lib/tron/abi/constant.rb
140
+ - lib/tron/abi/decoder.rb
141
+ - lib/tron/abi/encoder.rb
142
+ - lib/tron/abi/event.rb
143
+ - lib/tron/abi/function.rb
144
+ - lib/tron/abi/type.rb
145
+ - lib/tron/abi/util.rb
96
146
  - lib/tron/cache.rb
97
147
  - lib/tron/client.rb
98
148
  - lib/tron/configuration.rb
149
+ - lib/tron/contract.rb
150
+ - lib/tron/key.rb
151
+ - lib/tron/protobuf.rb
152
+ - lib/tron/protobuf/transaction_raw_serializer.rb
99
153
  - lib/tron/services/balance.rb
154
+ - lib/tron/services/contract.rb
100
155
  - lib/tron/services/price.rb
101
156
  - lib/tron/services/resources.rb
157
+ - lib/tron/services/transaction.rb
158
+ - lib/tron/signature.rb
159
+ - lib/tron/utils/abi.rb
102
160
  - lib/tron/utils/address.rb
103
161
  - lib/tron/utils/cache.rb
162
+ - lib/tron/utils/crypto.rb
104
163
  - lib/tron/utils/http.rb
105
164
  - lib/tron/utils/rate_limiter.rb
106
165
  - lib/tron/version.rb
107
- homepage: https://github.com/yourusername/tron
166
+ homepage: https://github.com/scionx-io/tron.rb
108
167
  licenses:
109
168
  - MIT
110
169
  metadata: {}
@@ -116,14 +175,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
175
  requirements:
117
176
  - - ">="
118
177
  - !ruby/object:Gem::Version
119
- version: '2.5'
178
+ version: '3.0'
120
179
  required_rubygems_version: !ruby/object:Gem::Requirement
121
180
  requirements:
122
181
  - - ">="
123
182
  - !ruby/object:Gem::Version
124
183
  version: '0'
125
184
  requirements: []
126
- rubygems_version: 3.1.6
185
+ rubygems_version: 3.5.22
127
186
  signing_key:
128
187
  specification_version: 4
129
188
  summary: Ruby wrapper for TRON blockchain APIs