erc20 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c9c69024f80c9041c0f80364a9e8129cf2d7802f9320576fbf007b9b3f32e9f
4
- data.tar.gz: 00f5eba51cde139b5a4c697253fc285152c52c06c8927cbdac34deb40863702b
3
+ metadata.gz: 85e0628229d427776681b41f5937a4ac7259333c946866c6662ce6a6b9ac32d9
4
+ data.tar.gz: 217938bd8b36af8844f3f3fc7f4f4f44d06af596cef01e3de46f017349f633ff
5
5
  SHA512:
6
- metadata.gz: 10d041c08ff2cbcb1e1fe7521980d26919b6b4926e1506a6341bd36280886cf26ee9d9192c4b2b3c4bf6e6e9237251a9fc3d4bda3430cdaaf54f229146b7febf
7
- data.tar.gz: 802187ea0f8acc530b22f9d5518b60e534a8a633eac114c0f5c682a8cc1b079edae4d130fc7ac1b6d52c3f24b443c2f3939b4727d61524ddca6fe2d94b90d726
6
+ metadata.gz: 7f9e60bab73c14a1ff6cacc2ef49b1ee7c615e0e36747b53540ef0988a7adbbb2482ce14eec32a393de56e853c4ae781b59a29df13fc4687fb4558e33f192d57
7
+ data.tar.gz: d472ce73882cf23a0a24f355961261cf03204c592eee0f8a439f2cb4e32ca76933e78cd563a4b2952c5050b1fe7eeef2ed2b9bceee7087ffda683a032abdeeaf
data/.rubocop.yml CHANGED
@@ -27,10 +27,10 @@ AllCops:
27
27
  TargetRubyVersion: 3.2
28
28
  SuggestExtensions: false
29
29
  NewCops: enable
30
- require:
31
- - rubocop-minitest
30
+ plugins:
32
31
  - rubocop-performance
33
32
  - rubocop-rake
33
+ - rubocop-minitest
34
34
  Minitest/EmptyLineBeforeAssertionMethods:
35
35
  Enabled: false
36
36
  Gemspec/RequiredRubyVersion:
data/Gemfile CHANGED
@@ -34,9 +34,9 @@ gem 'qbash', '>0', require: false
34
34
  gem 'rake', '13.2.1', require: false
35
35
  gem 'random-port', '>0', require: false
36
36
  gem 'rspec-rails', '7.1.1', require: false
37
- gem 'rubocop', '1.71.2', require: false
38
- gem 'rubocop-minitest', '0.36.0', require: false
39
- gem 'rubocop-performance', '1.23.1', require: false
37
+ gem 'rubocop', '1.72.1', require: false
38
+ gem 'rubocop-minitest', '0.37.1', require: false
39
+ gem 'rubocop-performance', '1.24.0', require: false
40
40
  gem 'rubocop-rake', '>0', require: false
41
41
  gem 'rubocop-rspec', '3.4.0', require: false
42
42
  gem 'simplecov', '0.22.0', require: false
data/Gemfile.lock CHANGED
@@ -103,6 +103,7 @@ GEM
103
103
  keccak (1.3.2)
104
104
  konstructor (1.0.2)
105
105
  language_server-protocol (3.17.0.4)
106
+ lint_roller (1.1.0)
106
107
  logger (1.6.6)
107
108
  loofah (2.24.0)
108
109
  crass (~> 1.0.2)
@@ -201,9 +202,10 @@ GEM
201
202
  rspec-mocks (~> 3.13)
202
203
  rspec-support (~> 3.13)
203
204
  rspec-support (3.13.2)
204
- rubocop (1.71.2)
205
+ rubocop (1.72.1)
205
206
  json (~> 2.3)
206
- language_server-protocol (>= 3.17.0)
207
+ language_server-protocol (~> 3.17.0.2)
208
+ lint_roller (~> 1.1.0)
207
209
  parallel (~> 1.10)
208
210
  parser (>= 3.3.0.2)
209
211
  rainbow (>= 2.2.2, < 4.0)
@@ -213,14 +215,17 @@ GEM
213
215
  unicode-display_width (>= 2.4.0, < 4.0)
214
216
  rubocop-ast (1.38.0)
215
217
  parser (>= 3.3.1.0)
216
- rubocop-minitest (0.36.0)
217
- rubocop (>= 1.61, < 2.0)
218
- rubocop-ast (>= 1.31.1, < 2.0)
219
- rubocop-performance (1.23.1)
220
- rubocop (>= 1.48.1, < 2.0)
221
- rubocop-ast (>= 1.31.1, < 2.0)
222
- rubocop-rake (0.6.0)
223
- rubocop (~> 1.0)
218
+ rubocop-minitest (0.37.1)
219
+ lint_roller (~> 1.1)
220
+ rubocop (>= 1.72.1, < 2.0)
221
+ rubocop-ast (>= 1.38.0, < 2.0)
222
+ rubocop-performance (1.24.0)
223
+ lint_roller (~> 1.1)
224
+ rubocop (>= 1.72.1, < 2.0)
225
+ rubocop-ast (>= 1.38.0, < 2.0)
226
+ rubocop-rake (0.7.0)
227
+ lint_roller (~> 1.1)
228
+ rubocop (>= 1.72.1)
224
229
  rubocop-rspec (3.4.0)
225
230
  rubocop (~> 1.61)
226
231
  ruby-progressbar (1.13.0)
@@ -238,7 +243,7 @@ GEM
238
243
  simplecov (~> 0.19)
239
244
  simplecov-html (0.13.1)
240
245
  simplecov_json_formatter (0.1.4)
241
- stringio (3.1.2)
246
+ stringio (3.1.3)
242
247
  tago (0.0.2)
243
248
  thor (1.3.2)
244
249
  threads (0.4.1)
@@ -282,9 +287,9 @@ DEPENDENCIES
282
287
  rake (= 13.2.1)
283
288
  random-port (> 0)
284
289
  rspec-rails (= 7.1.1)
285
- rubocop (= 1.71.2)
286
- rubocop-minitest (= 0.36.0)
287
- rubocop-performance (= 1.23.1)
290
+ rubocop (= 1.72.1)
291
+ rubocop-minitest (= 0.37.1)
292
+ rubocop-performance (= 1.24.0)
288
293
  rubocop-rake (> 0)
289
294
  rubocop-rspec (= 3.4.0)
290
295
  simplecov (= 0.22.0)
data/lib/erc20/erc20.rb CHANGED
@@ -42,5 +42,5 @@
42
42
  # License:: MIT
43
43
  module ERC20
44
44
  # Current version of the gem (changed by the +.rultor.yml+ on every release)
45
- VERSION = '0.0.12'
45
+ VERSION = '0.0.13'
46
46
  end
data/lib/erc20/wallet.rb CHANGED
@@ -93,13 +93,30 @@ class ERC20::Wallet
93
93
  def initialize(contract: USDT, chain: 1, log: $stdout,
94
94
  host: nil, port: 443, http_path: '/', ws_path: '/',
95
95
  ssl: true, proxy: nil)
96
+ raise 'Contract can\'t be nil' unless contract
97
+ raise 'Contract must be a String' unless contract.is_a?(String)
98
+ raise 'Invalid format of the contract' unless /^0x[0-9a-fA-F]{40}$/.match?(contract)
96
99
  @contract = contract
100
+ raise 'Host can\'t be nil' unless host
101
+ raise 'Host must be a String' unless host.is_a?(String)
97
102
  @host = host
103
+ raise 'Port can\'t be nil' unless port
104
+ raise 'Port must be an Integer' unless port.is_a?(Integer)
105
+ raise 'Port must be a positive Integer' unless port.positive?
98
106
  @port = port
107
+ raise 'Ssl can\'t be nil' if ssl.nil?
99
108
  @ssl = ssl
109
+ raise 'Http_path can\'t be nil' unless http_path
110
+ raise 'Http_path must be a String' unless http_path.is_a?(String)
100
111
  @http_path = http_path
112
+ raise 'Ws_path can\'t be nil' unless ws_path
113
+ raise 'Ws_path must be a String' unless ws_path.is_a?(String)
101
114
  @ws_path = ws_path
115
+ raise 'Log can\'t be nil' unless log
102
116
  @log = log
117
+ raise 'Chain can\'t be nil' unless chain
118
+ raise 'Chain must be an Integer' unless chain.is_a?(Integer)
119
+ raise 'Chain must be a positive Integer' unless chain.positive?
103
120
  @chain = chain
104
121
  @proxy = proxy
105
122
  @mutex = Mutex.new
@@ -110,6 +127,9 @@ class ERC20::Wallet
110
127
  # @param [String] hex Public key, in hex, starting from '0x'
111
128
  # @return [Integer] Balance, in tokens
112
129
  def balance(hex)
130
+ raise 'Address can\'t be nil' unless hex
131
+ raise 'Address must be a String' unless hex.is_a?(String)
132
+ raise 'Invalid format of the address' unless /^0x[0-9a-fA-F]{40}$/.match?(hex)
113
133
  func = '70a08231' # balanceOf
114
134
  padded = "000000000000000000000000#{hex[2..].downcase}"
115
135
  data = "0x#{func}#{padded}"
@@ -128,6 +148,23 @@ class ERC20::Wallet
128
148
  # @param [Integer] gas_price How much gas you pay per computation unit
129
149
  # @return [String] Transaction hash
130
150
  def pay(priv, address, amount, gas_limit: nil, gas_price: nil)
151
+ raise 'Private key can\'t be nil' unless priv
152
+ raise 'Private key must be a String' unless priv.is_a?(String)
153
+ raise 'Invalid format of private key' unless /^[0-9a-fA-F]{64}$/.match?(priv)
154
+ raise 'Address can\'t be nil' unless address
155
+ raise 'Address must be a String' unless address.is_a?(String)
156
+ raise 'Invalid format of the address' unless /^0x[0-9a-fA-F]{40}$/.match?(address)
157
+ raise 'Amount can\'t be nil' unless amount
158
+ raise 'Amount must be an Integer' unless amount.is_a?(Integer)
159
+ raise 'Amount must be a positive Integer' unless amount.positive?
160
+ if gas_limit
161
+ raise 'Gas limit must be an Integer' unless gas_limit.is_a?(Integer)
162
+ raise 'Gas limit must be a positive Integer' unless gas_limit.positive?
163
+ end
164
+ if gas_price
165
+ raise 'Gas price must be an Integer' unless gas_price.is_a?(Integer)
166
+ raise 'Gas price must be a positive Integer' unless gas_price.positive?
167
+ end
131
168
  func = 'a9059cbb' # transfer(address,uint256)
132
169
  to_clean = address.downcase.sub(/^0x/, '')
133
170
  to_padded = ('0' * (64 - to_clean.size)) + to_clean
@@ -169,14 +206,21 @@ class ERC20::Wallet
169
206
  # Once we actually start listening, the +active+ array will be updated
170
207
  # with the list of addresses.
171
208
  #
172
- # Both +addresses+ and +active+ must have two methods implemented: +to_a()+
173
- # and +append()+. Only these methods will be called.
209
+ # The +addresses+ must have +to_a()+ implemented.
210
+ # The +active+ must have +append()+ implemented.
211
+ # Only these methods will be called.
174
212
  #
175
213
  # @param [Array<String>] addresses Addresses to monitor
176
214
  # @param [Array] active List of addresses that we are actually listening to
177
215
  # @param [Boolean] raw TRUE if you need to get JSON events as they arrive from Websockets
178
216
  # @param [Integer] delay How many seconds to wait between +eth_subscribe+ calls
179
217
  def accept(addresses, active = [], raw: false, delay: 1)
218
+ raise 'Addresses can\'t be nil' unless addresses
219
+ raise 'Addresses must respond to .to_a()' unless addresses.respond_to?(:to_a)
220
+ raise 'Active can\'t be nil' unless active
221
+ raise 'Active must respond to .append()' unless addresses.respond_to?(:append)
222
+ raise 'Amount must be an Integer' unless delay.is_a?(Integer)
223
+ raise 'Amount must be a positive Integer' unless delay.positive?
180
224
  EventMachine.run do
181
225
  u = url(http: false)
182
226
  @log.debug("Connecting to #{u.hostname}:#{u.port}...")
@@ -192,12 +236,7 @@ class ERC20::Wallet
192
236
  end
193
237
  ws.on(:message) do |msg|
194
238
  verbose do
195
- data =
196
- begin
197
- JSON.parse(msg.data)
198
- rescue StandardError
199
- {}
200
- end
239
+ data = to_json(msg)
201
240
  if data['id']
202
241
  before = active.to_a
203
242
  attempt.each do |a|
@@ -265,6 +304,12 @@ class ERC20::Wallet
265
304
 
266
305
  private
267
306
 
307
+ def to_json(msg)
308
+ JSON.parse(msg.data)
309
+ rescue StandardError
310
+ {}
311
+ end
312
+
268
313
  def verbose
269
314
  yield
270
315
  rescue StandardError => e
@@ -33,6 +33,10 @@ require 'typhoeus'
33
33
  require_relative '../../lib/erc20/fake_wallet'
34
34
  require_relative '../test__helper'
35
35
 
36
+ k = Eth::Key.new
37
+ puts k.private_hex
38
+ puts k.address
39
+
36
40
  # Test.
37
41
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
38
42
  # Copyright:: Copyright (c) 2025 Yegor Bugayenko
@@ -38,9 +38,9 @@ require_relative '../test__helper'
38
38
  # Copyright:: Copyright (c) 2025 Yegor Bugayenko
39
39
  # License:: MIT
40
40
  class TestWallet < Minitest::Test
41
- # At this address, in Etherium mainnet, there are a ~$27 USDT. I won't
41
+ # At this address, in Etherium mainnet, there are $8 USDT. I won't
42
42
  # move them anyway, that's why tests can use this address forever.
43
- STABLE = '0xEB2fE8872A6f1eDb70a2632EA1f869AB131532f6'
43
+ STABLE = '0x7232148927F8a580053792f44D4d59d40Fd00ABD'
44
44
 
45
45
  # One guy private hex.
46
46
  JEFF = '81a9b2114d53731ecc84b261ef6c0387dde34d5907fe7b441240cc21d61bf80a'
@@ -51,7 +51,7 @@ class TestWallet < Minitest::Test
51
51
  def test_checks_balance_on_mainnet
52
52
  b = mainnet.balance(STABLE)
53
53
  refute_nil(b)
54
- assert_equal(27_258_889, b)
54
+ assert_equal(8_000_000, b)
55
55
  end
56
56
 
57
57
  def test_checks_balance_of_absent_address
@@ -253,11 +253,21 @@ class TestWallet < Minitest::Test
253
253
  host: 'mainnet.infura.io', http_path: "/v3/#{env('INFURA_KEY')}",
254
254
  proxy:, log: loog
255
255
  )
256
- assert_equal(27_258_889, w.balance(STABLE))
256
+ assert_equal(8_000_000, w.balance(STABLE))
257
257
  end
258
258
  end
259
259
  end
260
260
 
261
+ def test_pays_on_mainnet
262
+ skip('This is live, must be run manually')
263
+ w = mainnet
264
+ print 'Enter Etherium ERC20 private key (64 chars): '
265
+ priv = gets.chomp
266
+ to = '0xEB2fE8872A6f1eDb70a2632EA1f869AB131532f6'
267
+ txn = w.pay(priv, to, 1_990_000)
268
+ assert_equal(66, txn.length)
269
+ end
270
+
261
271
  private
262
272
 
263
273
  def env(var)
data/test/test__helper.rb CHANGED
@@ -64,12 +64,13 @@ class Minitest::Test
64
64
  ENV['RAKE'] ? Loog::ERRORS : Loog::VERBOSE
65
65
  end
66
66
 
67
- def wait_for
67
+ def wait_for(seconds = 30)
68
68
  start = Time.now
69
69
  loop do
70
70
  sleep(0.1)
71
71
  break if yield
72
- raise 'timeout' if Time.now - start > 60
72
+ passed = Time.now - start
73
+ raise "Giving up after #{passed} seconds of waiting" if passed > seconds
73
74
  rescue Errno::ECONNREFUSED
74
75
  retry
75
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erc20
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-02-14 00:00:00.000000000 Z
11
+ date: 2025-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eth