erc20 0.0.4 → 0.0.5

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: 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: []