erc20 0.0.4 → 0.0.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b5bccf0ea259136bad39ab36f01240da8a029958b627ed337cd20477a7a13c9
4
- data.tar.gz: 4c5d605e086d38755d25d8153c0bf6b220460f5b984607fd304706fe0b3d942f
3
+ metadata.gz: 14d84ab9ee2ac821f5f404dcea22437f622fe82bf5565a04c695f718974ba129
4
+ data.tar.gz: d2ec55f58ef13c62abfb0b870d541d3cc5bd8a32f5c685eda64fb484558af332
5
5
  SHA512:
6
- metadata.gz: 0adbab22a3b752f63e1e001eac554ba8bcc8a40a2fea7234b9d674608eb281c912fb2e21931497006509b8cf2ae80e82d9de8dd49b7727f48759796da375d43b
7
- data.tar.gz: ae3387a6c71c5ba367c8bd5814d2eebced21d6de6087dc214b083659811e2ed60efb5d0d981b7ba57b10030435566645ddd8328ac99ef4f9574b534192385383
6
+ metadata.gz: 2ef86114757f0b841b022a8cef64330610d68425d13e900487e4d99589065ed19640f393986f3ea62003fe2d24ae93513406611d4725d58dcc3165e7e70a5ffa
7
+ data.tar.gz: 92855745194e5cf9b6ff1902f0f7e4f44606aa4e306313668e7fb01849ab91e10fccf99e6f7ac6dfa0a6e176abc6d7aaa30f279b88e7c0f94b1133380f61d643
data/Gemfile CHANGED
@@ -25,6 +25,7 @@ gemspec
25
25
 
26
26
  gem 'backtrace', '>0', require: false
27
27
  gem 'donce', '>0', require: false
28
+ gem 'faraday', '>0', require: false
28
29
  gem 'loog', '>0', require: false
29
30
  gem 'minitest', '5.25.4', require: false
30
31
  gem 'minitest-reporters', '1.7.1', require: false
data/Gemfile.lock CHANGED
@@ -2,11 +2,11 @@ PATH
2
2
  remote: .
3
3
  specs:
4
4
  erc20 (0.0.0)
5
- backtrace (> 0)
6
- eth (~> 0.4)
7
- jsonrpc-client (> 0)
5
+ eth (>= 0.5.13)
6
+ faye-websocket (>= 0.11.3)
7
+ json (>= 2.10.1)
8
+ jsonrpc-client (>= 0.1.4)
8
9
  loog (> 0)
9
- websocket-client-simple (> 0)
10
10
 
11
11
  GEM
12
12
  remote: https://rubygems.org/
@@ -71,13 +71,16 @@ GEM
71
71
  scrypt (~> 3.0)
72
72
  ethon (0.16.0)
73
73
  ffi (>= 1.15.0)
74
- event_emitter (0.2.6)
74
+ eventmachine (1.2.7)
75
75
  faraday (2.12.2)
76
76
  faraday-net_http (>= 2.0, < 3.5)
77
77
  json
78
78
  logger
79
79
  faraday-net_http (3.4.0)
80
80
  net-http (>= 0.5.0)
81
+ faye-websocket (0.11.3)
82
+ eventmachine (>= 0.12.0)
83
+ websocket-driver (>= 0.5.1)
81
84
  ffi (1.17.1-arm64-darwin)
82
85
  ffi (1.17.1-x64-mingw-ucrt)
83
86
  ffi (1.17.1-x86_64-darwin)
@@ -93,7 +96,7 @@ GEM
93
96
  pp (>= 0.6.0)
94
97
  rdoc (>= 4.0.0)
95
98
  reline (>= 0.4.2)
96
- json (2.10.0)
99
+ json (2.10.1)
97
100
  jsonrpc-client (0.1.4)
98
101
  faraday
99
102
  multi_json (>= 1.1.0)
@@ -115,7 +118,6 @@ GEM
115
118
  minitest-retry (0.2.5)
116
119
  minitest (>= 5.0)
117
120
  multi_json (1.15.0)
118
- mutex_m (0.3.0)
119
121
  net-http (0.6.0)
120
122
  uri
121
123
  nokogiri (1.18.2-arm64-darwin)
@@ -251,12 +253,10 @@ GEM
251
253
  unicode-emoji (4.0.4)
252
254
  uri (1.0.2)
253
255
  useragent (0.16.11)
254
- websocket (1.2.11)
255
- websocket-client-simple (0.9.0)
256
+ websocket-driver (0.7.7)
256
257
  base64
257
- event_emitter
258
- mutex_m
259
- websocket
258
+ websocket-extensions (>= 0.1.0)
259
+ websocket-extensions (0.1.5)
260
260
  yard (0.9.37)
261
261
  zeitwerk (2.7.1)
262
262
 
@@ -273,6 +273,7 @@ DEPENDENCIES
273
273
  backtrace (> 0)
274
274
  donce (> 0)
275
275
  erc20!
276
+ faraday (> 0)
276
277
  loog (> 0)
277
278
  minitest (= 5.25.4)
278
279
  minitest-reporters (= 1.7.1)
data/README.md CHANGED
@@ -23,18 +23,19 @@ require 'erc20'
23
23
  w = ERC20::Wallet.new(
24
24
  contract: ERC20::Wallet.USDT, # hex of it
25
25
  host: 'mainnet.infura.io',
26
- path: '/v3/<your-key>',
26
+ http_path: '/v3/<your-infura-key>',
27
+ ws_path: '/ws/v3/<your-infura-key>',
27
28
  log: $stdout
28
29
  )
29
30
 
30
- # Check balance on the address:
31
+ # Check how many ERC20 tokens are on the given address:
31
32
  usdt = w.balance(address)
32
33
 
33
- # Send a few tokens to someone and get transaction hash:
34
- txn = w.pay(private_key, to_address, amount)
34
+ # Send a few ERC20 tokens to someone and get transaction hash:
35
+ hex = w.pay(private_key, to_address, amount)
35
36
 
36
- # Stay waiting, and trigger the block when transactions arrive:
37
- addresses = ['0x...', '0x...']
37
+ # Stay waiting, and trigger the block when new ERC20 payments show up:
38
+ addresses = ['0x...', '0x...'] # only wait for payments to these addresses
38
39
  w.accept(addresses) do |event|
39
40
  puts event[:amount] # how much
40
41
  puts event[:from] # who sent the payment
@@ -55,6 +56,22 @@ To get address from private one:
55
56
  public_hex = Eth::Key.new(priv: key).address
56
57
  ```
57
58
 
59
+ To connect to the server via [HTTP proxy] with [basic authentication]:
60
+
61
+ ```ruby
62
+ w = ERC20::Wallet.new(
63
+ host: 'go.getblock.io',
64
+ http_path: '/<your-rpc-getblock-key>',
65
+ ws_path: '/<your-ws-getblock-key>',
66
+ proxy: 'http://jeffrey:swordfish@example.com:3128' # here!
67
+ )
68
+ ```
69
+
70
+ You can use [squid-proxy] [Docker] image to set up your own [HTTP proxy] server.
71
+
72
+ Of course, this library works with [Polygon], [Optimism],
73
+ and other forks of [Etherium].
74
+
58
75
  ## How to contribute
59
76
 
60
77
  Read
@@ -78,3 +95,9 @@ If it's clean and you don't see any error messages, submit your pull request.
78
95
  [Infura]: https://infura.io/
79
96
  [Alchemy]: https://alchemy.com/
80
97
  [GetBlock]: https://getblock.io/
98
+ [basic authentication]: https://en.wikipedia.org/wiki/Basic_access_authentication
99
+ [HTTP proxy]: https://en.wikipedia.org/wiki/Proxy_server
100
+ [squid-proxy]: https://github.com/yegor256/squid-proxy
101
+ [Docker]: https://www.docker.com/
102
+ [Polygon]: https://polygon.technology/
103
+ [Optimism]: https://www.optimism.io/
data/Rakefile CHANGED
@@ -24,6 +24,8 @@ require 'rubygems'
24
24
  require 'rake'
25
25
  require 'rake/clean'
26
26
 
27
+ ENV['RAKE'] = 'true'
28
+
27
29
  def name
28
30
  @name ||= File.basename(Dir['*.gemspec'].first, '.*')
29
31
  end
data/erc20.gemspec CHANGED
@@ -31,18 +31,20 @@ Gem::Specification.new do |s|
31
31
  s.license = 'MIT'
32
32
  s.summary = 'Sending and receiving ERC20 tokens in Etherium network'
33
33
  s.description =
34
- 'A simple library for making ERC20 manipulations as easy as they' \
35
- 'can be for cryptocurrency newbies'
34
+ 'A simple library for making ERC20 manipulations as easy as they ' \
35
+ 'can be for cryptocurrency newbies: checking balance, sending payments, ' \
36
+ 'and monitoring addresses for incoming payments. The library expects ' \
37
+ 'Etherium node to provide JSON RPC and Websockets API.'
36
38
  s.authors = ['Yegor Bugayenko']
37
39
  s.email = 'yegor256@gmail.com'
38
40
  s.homepage = 'http://github.com/yegor256/erc20.rb'
39
41
  s.files = `git ls-files`.split($RS)
40
42
  s.rdoc_options = ['--charset=UTF-8']
41
43
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
42
- s.add_dependency 'backtrace', '>0'
43
- s.add_dependency 'eth', '~>0.4'
44
- s.add_dependency 'jsonrpc-client', '>0'
44
+ s.add_dependency 'eth', '>=0.5.13'
45
+ s.add_dependency 'faye-websocket', '>=0.11.3'
46
+ s.add_dependency 'json', '>=2.10.1'
47
+ s.add_dependency 'jsonrpc-client', '>=0.1.4'
45
48
  s.add_dependency 'loog', '>0'
46
- s.add_dependency 'websocket-client-simple', '>0'
47
49
  s.metadata['rubygems_mfa_required'] = 'true'
48
50
  end
data/lib/erc20/wallet.rb CHANGED
@@ -21,9 +21,12 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'eth'
24
+ require 'eventmachine'
25
+ require 'faye/websocket'
26
+ require 'json'
24
27
  require 'jsonrpc/client'
25
28
  require 'loog'
26
- require 'websocket-client-simple'
29
+ require 'uri'
27
30
  require_relative '../erc20'
28
31
 
29
32
  # A wallet.
@@ -37,34 +40,31 @@ class ERC20::Wallet
37
40
  # Address of USDT contract.
38
41
  USDT = '0xdac17f958d2ee523a2206206994597c13d831ec7'
39
42
 
43
+ # These properties are read-only:
44
+ attr_reader :host, :port, :ssl, :chain, :contract, :ws_path, :http_path
45
+
40
46
  # Constructor.
41
47
  # @param [String] contract Hex of the contract in Etherium
42
- # @param [String] rpc The URL of Etherium JSON-RPC provider
43
48
  # @param [Integer] chain The ID of the chain (1 for mainnet)
44
49
  # @param [String] host The host to connect to
45
50
  # @param [Integer] port TCP port to use
46
- # @param [String] path The path in the connection URL
51
+ # @param [String] http_path The path in the connection URL, for HTTP RPC
52
+ # @param [String] ws_path The path in the connection URL, for Websockets
47
53
  # @param [Boolean] ssl Should we use SSL (for https and wss)
54
+ # @param [String] proxy The URL of the proxy to use
48
55
  # @param [Object] log The destination for logs
49
- def initialize(contract: USDT, rpc: nil, wss: nil, chain: 1, log: $stdout,
50
- host: nil, port: 443, path: '/', ssl: true)
56
+ def initialize(contract: USDT, chain: 1, log: $stdout,
57
+ host: nil, port: 443, http_path: '/', ws_path: '/',
58
+ ssl: true, proxy: nil)
51
59
  @contract = contract
52
- raise 'Use either host or rpc' if rpc && host
53
- raise 'Use either host or wss' if wss && host
54
- if rpc
55
- @rpc = rpc
56
- else
57
- raise 'Either rpc or host+port+path are required' unless host && port && path
58
- @rpc = "http#{ssl ? 's' : ''}://#{host}:#{port}#{path}"
59
- end
60
- if wss
61
- @wss = wss
62
- else
63
- raise 'Either wss or host+port+path are required' unless host && port && path
64
- @wss = "http#{ssl ? 's' : ''}://#{host}:#{port}#{path}"
65
- end
60
+ @host = host
61
+ @port = port
62
+ @ssl = ssl
63
+ @http_path = http_path
64
+ @ws_path = ws_path
66
65
  @log = log
67
66
  @chain = chain
67
+ @proxy = proxy
68
68
  end
69
69
 
70
70
  # Get balance of a public address.
@@ -119,35 +119,39 @@ class ERC20::Wallet
119
119
 
120
120
  # Wait for incoming transactions and let the block know when they
121
121
  # arrive. It's a blocking call, it's better to run it in a separate
122
- # thread.
122
+ # thread. It will never finish. In order to stop it, you should do
123
+ # +Thread.kill+.
123
124
  #
124
125
  # @param [Array<String>] addresses Addresses to monitor
125
126
  # @param [Array] ready When connected, TRUE will be added to this array
126
127
  # @param [Boolean] raw TRUE if you need to get JSON events as they arrive from Websockets
127
128
  def accept(addresses, connected: [], raw: false)
128
- WebSocket::Client::Simple.connect(@wss) do |ws|
129
+ EM.run do
130
+ u = url(http: false)
131
+ @log.debug("Connecting to #{u}...")
132
+ ws = Faye::WebSocket::Client.new(u, [], proxy: @proxy ? { origin: @proxy } : {})
129
133
  log = @log
130
134
  contract = @contract
131
- wss = @wss
132
135
  ws.on(:open) do
133
- log.debug("Connected to #{wss}")
134
- msg = {
135
- jsonrpc: '2.0',
136
- id: 1,
137
- method: 'eth_subscribe',
138
- params: [
139
- 'logs',
140
- {
141
- address: contract,
142
- topics: [
143
- '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
144
- nil,
145
- addresses.map { |a| "0x000000000000000000000000#{a[2..]}" }
146
- ]
147
- }
148
- ]
149
- }
150
- ws.send(msg.to_json)
136
+ log.debug("Connected to #{@host}")
137
+ ws.send(
138
+ {
139
+ jsonrpc: '2.0',
140
+ id: 1,
141
+ method: 'eth_subscribe',
142
+ params: [
143
+ 'logs',
144
+ {
145
+ address: contract,
146
+ topics: [
147
+ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
148
+ nil,
149
+ addresses.map { |a| "0x000000000000000000000000#{a[2..]}" }
150
+ ]
151
+ }
152
+ ]
153
+ }.to_json
154
+ )
151
155
  connected.append(1)
152
156
  log.debug("Subscribed to #{addresses.count} addresses")
153
157
  end
@@ -172,19 +176,35 @@ class ERC20::Wallet
172
176
  end
173
177
  end
174
178
  ws.on(:close) do |_e|
175
- log.debug("Disconnected from #{wss}")
179
+ log.debug("Disconnected from #{@host}")
176
180
  end
177
181
  ws.on(:error) do |e|
178
- log.debug("Error at #{wss}: #{e}")
182
+ log.debug("Error at #{@host}: #{e.message}")
179
183
  end
180
184
  end
181
185
  end
182
186
 
183
187
  private
184
188
 
189
+ def url(http: true)
190
+ "#{http ? 'http' : 'ws'}#{@ssl ? 's' : ''}://#{@host}:#{@port}#{http ? @http_path : @ws_path}"
191
+ end
192
+
185
193
  def jsonrpc
186
194
  JSONRPC.logger = Loog::NULL
187
- JSONRPC::Client.new(@rpc)
195
+ connection =
196
+ if @proxy
197
+ uri = URI.parse(@proxy)
198
+ Faraday.new do |f|
199
+ f.adapter(Faraday.default_adapter)
200
+ f.proxy = {
201
+ uri: "#{uri.scheme}://#{uri.hostname}:#{uri.port}",
202
+ user: uri.user,
203
+ password: uri.password
204
+ }
205
+ end
206
+ end
207
+ JSONRPC::Client.new(url, connection:)
188
208
  end
189
209
 
190
210
  def gas_estimate(from, data)
data/lib/erc20.rb CHANGED
@@ -27,5 +27,5 @@
27
27
  # License:: MIT
28
28
  module ERC20
29
29
  # Current version of the gem (changed by .rultor.yml on every release)
30
- VERSION = '0.0.4'
30
+ VERSION = '0.0.5'
31
31
  end
@@ -23,22 +23,24 @@
23
23
  require 'backtrace'
24
24
  require 'donce'
25
25
  require 'eth'
26
+ require 'faraday'
26
27
  require 'loog'
28
+ require 'minitest/autorun'
27
29
  require 'random-port'
28
30
  require 'shellwords'
29
31
  require 'typhoeus'
30
- require 'minitest/autorun'
31
32
  require_relative '../../lib/erc20'
32
33
  require_relative '../../lib/erc20/wallet'
34
+ require_relative '../test__helper'
33
35
 
34
36
  # Test.
35
37
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
36
38
  # Copyright:: Copyright (c) 2025 Yegor Bugayenko
37
39
  # License:: MIT
38
40
  class TestWallet < Minitest::Test
39
- # At this address, in the mainnet, there are a few USDT tokens. I won't
41
+ # At this address, in Etherium mainnet, there are a few USDT tokens. I won't
40
42
  # move them anyway, that's why tests can use this address forever.
41
- STABLE_ADDRESS = '0xEB2fE8872A6f1eDb70a2632EA1f869AB131532f6'
43
+ STABLE = '0xEB2fE8872A6f1eDb70a2632EA1f869AB131532f6'
42
44
 
43
45
  # One guy private hex.
44
46
  JEFF = '81a9b2114d53731ecc84b261ef6c0387dde34d5907fe7b441240cc21d61bf80a'
@@ -47,7 +49,7 @@ class TestWallet < Minitest::Test
47
49
  WALTER = '91f9111b1744d55361e632771a4e53839e9442a9fef45febc0a5c838c686a15b'
48
50
 
49
51
  def test_checks_balance_on_mainnet
50
- b = mainnet.balance(STABLE_ADDRESS)
52
+ b = mainnet.balance(STABLE)
51
53
  refute_nil(b)
52
54
  assert_equal(27_258_889, b)
53
55
  end
@@ -61,18 +63,28 @@ class TestWallet < Minitest::Test
61
63
 
62
64
  def test_fails_with_invalid_infura_key
63
65
  w = ERC20::Wallet.new(
64
- rpc: 'https://mainnet.infura.io/v3/invalid-key-here',
65
- wss: 'https://mainnet.infura.io/v3/another-invalid-key-here',
66
- log: Loog::NULL
66
+ host: 'mainnet.infura.io',
67
+ http_path: '/v3/invalid-key-here',
68
+ log: loog
67
69
  )
68
- assert_raises(StandardError) { w.balance(STABLE_ADDRESS) }
70
+ assert_raises(StandardError) { w.balance(STABLE) }
69
71
  end
70
72
 
71
73
  def test_checks_balance_on_testnet
72
- skip('does not work')
73
- b = testnet.balance(STABLE_ADDRESS)
74
+ b = testnet.balance(STABLE)
75
+ refute_nil(b)
76
+ assert_predicate(b, :zero?)
77
+ end
78
+
79
+ def test_checks_balance_on_polygon
80
+ w = ERC20::Wallet.new(
81
+ contract: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
82
+ host: 'polygon-mainnet.infura.io', http_path: "/v3/#{env('INFURA_KEY')}",
83
+ log: loog
84
+ )
85
+ b = w.balance(STABLE)
74
86
  refute_nil(b)
75
- assert_predicate(b, :positive?)
87
+ assert_predicate(b, :zero?)
76
88
  end
77
89
 
78
90
  def test_checks_balance_on_hardhat
@@ -106,7 +118,7 @@ class TestWallet < Minitest::Test
106
118
  event = e
107
119
  end
108
120
  rescue StandardError => e
109
- puts Backtrace.new(e)
121
+ loog.error(Backtrace.new(e))
110
122
  end
111
123
  wait_for { !connected.empty? }
112
124
  sum = 77_000
@@ -120,8 +132,80 @@ class TestWallet < Minitest::Test
120
132
  end
121
133
  end
122
134
 
135
+ def test_accepts_payments_on_hardhat_via_proxy
136
+ via_proxy do |proxy|
137
+ walter = Eth::Key.new(priv: WALTER).address.to_s.downcase
138
+ jeff = Eth::Key.new(priv: JEFF).address.to_s.downcase
139
+ on_hardhat do |w|
140
+ wallet = through_proxy(w, proxy)
141
+ connected = []
142
+ event = nil
143
+ daemon =
144
+ Thread.new do
145
+ wallet.accept([walter, jeff], connected:) do |e|
146
+ event = e
147
+ end
148
+ rescue StandardError => e
149
+ loog.error(Backtrace.new(e))
150
+ end
151
+ wait_for { !connected.empty? }
152
+ sum = 55_000
153
+ wallet.pay(JEFF, walter, sum)
154
+ wait_for { !event.nil? }
155
+ daemon.kill
156
+ daemon.join(30)
157
+ assert_equal(sum, event[:amount])
158
+ end
159
+ end
160
+ end
161
+
162
+ def test_accepts_payments_on_mainnet
163
+ connected = []
164
+ failed = false
165
+ net = mainnet
166
+ daemon =
167
+ Thread.new do
168
+ net.accept([STABLE], connected:) do |_|
169
+ # ignore it
170
+ end
171
+ rescue StandardError => e
172
+ failed = true
173
+ loog.error(Backtrace.new(e))
174
+ end
175
+ wait_for { !connected.empty? }
176
+ daemon.kill
177
+ daemon.join(30)
178
+ refute(failed)
179
+ end
180
+
181
+ def test_checks_balance_via_proxy
182
+ via_proxy do |proxy|
183
+ on_hardhat do |w|
184
+ wallet = through_proxy(w, proxy)
185
+ b = wallet.balance(Eth::Key.new(priv: JEFF).address.to_s)
186
+ assert_equal(123_000_100_000, b)
187
+ end
188
+ end
189
+ end
190
+
191
+ def test_checks_balance_via_proxy_on_mainnet
192
+ via_proxy do |proxy|
193
+ on_hardhat do
194
+ w = ERC20::Wallet.new(
195
+ host: 'mainnet.infura.io', http_path: "/v3/#{env('INFURA_KEY')}",
196
+ proxy:, log: loog
197
+ )
198
+ assert_equal(27_258_889, w.balance(STABLE))
199
+ end
200
+ end
201
+ end
202
+
123
203
  private
124
204
 
205
+ def loog
206
+ ENV['RAKE'] ? Loog::NULL : Loog::VERBOSE
207
+ end
208
+
125
209
  def wait_for
126
210
  start = Time.now
127
211
  loop do
@@ -145,29 +229,66 @@ class TestWallet < Minitest::Test
145
229
 
146
230
  def mainnet
147
231
  [
148
- "https://mainnet.infura.io/v3/#{env('INFURA_KEY')}",
149
- "https://go.getblock.io/#{env('GETBLOCK_KEY')}"
150
- ].map do |url|
151
- ERC20::Wallet.new(rpc: url, wss: url, log: Loog::NULL)
232
+ {
233
+ host: 'mainnet.infura.io',
234
+ http_path: "/v3/#{env('INFURA_KEY')}",
235
+ ws_path: "/ws/v3/#{env('INFURA_KEY')}"
236
+ },
237
+ {
238
+ host: 'go.getblock.io',
239
+ http_path: "/#{env('GETBLOCK_KEY')}",
240
+ ws_path: "/#{env('GETBLOCK_WS_KEY')}"
241
+ }
242
+ ].map do |server|
243
+ ERC20::Wallet.new(host: server[:host], http_path: server[:http_path], ws_path: server[:ws_path], log: loog)
152
244
  end.sample
153
245
  end
154
246
 
155
247
  def testnet
156
248
  [
157
- "https://sepolia.infura.io/v3/#{env('INFURA_KEY')}",
158
- "https://go.getblock.io/#{env('GETBLOCK_SEPOILA_KEY')}"
159
- ].map do |url|
160
- ERC20::Wallet.new(rpc: url, wss: url, log: Loog::NULL)
249
+ {
250
+ host: 'sepolia.infura.io',
251
+ http_path: "/v3/#{env('INFURA_KEY')}",
252
+ ws_path: "/ws/v3/#{env('INFURA_KEY')}"
253
+ },
254
+ {
255
+ host: 'go.getblock.io',
256
+ http_path: "/#{env('GETBLOCK_SEPOILA_KEY')}",
257
+ ws_path: "/#{env('GETBLOCK_SEPOILA_KEY')}"
258
+ }
259
+ ].map do |server|
260
+ ERC20::Wallet.new(host: server[:host], http_path: server[:http_path], ws_path: server[:ws_path], log: loog)
161
261
  end.sample
162
262
  end
163
263
 
264
+ def through_proxy(wallet, proxy)
265
+ ERC20::Wallet.new(
266
+ contract: wallet.contract, chain: wallet.chain,
267
+ host: donce_host, port: wallet.port, http_path: wallet.http_path, ws_path: wallet.ws_path,
268
+ ssl: wallet.ssl, proxy:, log: loog
269
+ )
270
+ end
271
+
272
+ def via_proxy
273
+ RandomPort::Pool::SINGLETON.acquire do |port|
274
+ donce(
275
+ image: 'yegor256/squid-proxy:latest',
276
+ ports: { port => 3128 },
277
+ env: { 'USERNAME' => 'jeffrey', 'PASSWORD' => 'swordfish' },
278
+ root: true, log: loog
279
+ ) do
280
+ yield "http://jeffrey:swordfish@localhost:#{port}"
281
+ end
282
+ end
283
+ end
284
+
164
285
  def on_hardhat
165
286
  RandomPort::Pool::SINGLETON.acquire do |port|
166
287
  donce(
167
288
  home: File.join(__dir__, '../../hardhat'),
168
289
  ports: { port => 8545 },
169
290
  command: 'npx hardhat node',
170
- log: Loog::NULL
291
+ log: loog
171
292
  ) do
172
293
  wait_for_port(port)
173
294
  cmd = [
@@ -180,13 +301,13 @@ class TestWallet < Minitest::Test
180
301
  home: File.join(__dir__, '../../hardhat'),
181
302
  command: "/bin/bash -c #{Shellwords.escape(cmd)}",
182
303
  build_args: { 'HOST' => donce_host, 'PORT' => port },
183
- log: Loog::NULL,
304
+ log: loog,
184
305
  root: true
185
306
  ).split("\n").last
186
307
  wallet = ERC20::Wallet.new(
187
308
  contract:, chain: 4242,
188
- host: 'localhost', port:, path: '/', ssl: false,
189
- log: Loog::NULL
309
+ host: 'localhost', port:, http_path: '/', ws_path: '/', ssl: false,
310
+ log: loog
190
311
  )
191
312
  yield wallet
192
313
  end
data/test/test__helper.rb CHANGED
@@ -35,5 +35,7 @@ require 'minitest/reporters'
35
35
  Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new]
36
36
 
37
37
  # To make tests retry on failure:
38
- require 'minitest/retry'
39
- Minitest::Retry.use!(methods_to_skip: [])
38
+ if ENV['RAKE']
39
+ require 'minitest/retry'
40
+ Minitest::Retry.use!(methods_to_skip: [])
41
+ end
metadata CHANGED
@@ -1,73 +1,73 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erc20
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
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-10 00:00:00.000000000 Z
11
+ date: 2025-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: backtrace
14
+ name: eth
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 0.5.13
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'
26
+ version: 0.5.13
27
27
  - !ruby/object:Gem::Dependency
28
- name: eth
28
+ name: faye-websocket
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0.4'
33
+ version: 0.11.3
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: '0.4'
40
+ version: 0.11.3
41
41
  - !ruby/object:Gem::Dependency
42
- name: jsonrpc-client
42
+ name: json
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 2.10.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 2.10.1
55
55
  - !ruby/object:Gem::Dependency
56
- name: loog
56
+ name: jsonrpc-client
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 0.1.4
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: 0.1.4
69
69
  - !ruby/object:Gem::Dependency
70
- name: websocket-client-simple
70
+ name: loog
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">"
@@ -80,8 +80,10 @@ dependencies:
80
80
  - - ">"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- description: A simple library for making ERC20 manipulations as easy as theycan be
84
- for cryptocurrency newbies
83
+ description: 'A simple library for making ERC20 manipulations as easy as they can
84
+ be for cryptocurrency newbies: checking balance, sending payments, and monitoring
85
+ addresses for incoming payments. The library expects Etherium node to provide JSON
86
+ RPC and Websockets API.'
85
87
  email: yegor256@gmail.com
86
88
  executables: []
87
89
  extensions: []