erc20 0.0.3 → 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: 9b1ea9500a3c12a4b5f84d2aa2101e16c3cfcf1fef9f0d8ccb95433aba9798cb
4
- data.tar.gz: dcd57712fa1fd1adb99511cbc42cb1c2315e7178b9d90862bddfb632ec83b0fc
3
+ metadata.gz: 14d84ab9ee2ac821f5f404dcea22437f622fe82bf5565a04c695f718974ba129
4
+ data.tar.gz: d2ec55f58ef13c62abfb0b870d541d3cc5bd8a32f5c685eda64fb484558af332
5
5
  SHA512:
6
- metadata.gz: dada085699673561fff510ba8d2071d983c36634b7a7bdf0232536ee4319469a4cd19d7f6b5b48ec6572ec974eeaa5fe192052210b985fb3a094bfbf5b97c8be
7
- data.tar.gz: 306828e368f07f87274eeaf1439075bc11a7b858260997419df4620b94682156b3d77000d9d5245aba5397507a0de107339f4d13b354cf3291cf592437884a69
6
+ metadata.gz: 2ef86114757f0b841b022a8cef64330610d68425d13e900487e4d99589065ed19640f393986f3ea62003fe2d24ae93513406611d4725d58dcc3165e7e70a5ffa
7
+ data.tar.gz: 92855745194e5cf9b6ff1902f0f7e4f44606aa4e306313668e7fb01849ab91e10fccf99e6f7ac6dfa0a6e176abc6d7aaa30f279b88e7c0f94b1133380f61d643
data/.rubocop.yml CHANGED
@@ -43,6 +43,8 @@ Layout/MultilineMethodCallIndentation:
43
43
  Enabled: false
44
44
  Metrics/AbcSize:
45
45
  Enabled: false
46
+ Metrics/ParameterLists:
47
+ Enabled: false
46
48
  Metrics/BlockLength:
47
49
  Max: 100
48
50
  Metrics/CyclomaticComplexity:
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
@@ -22,19 +22,20 @@ as simple as they can be, if you have a provider of
22
22
  require 'erc20'
23
23
  w = ERC20::Wallet.new(
24
24
  contract: ERC20::Wallet.USDT, # hex of it
25
- rpc: 'https://mainnet.infura.io/v3/<your-key>',
26
- wss: 'wss://mainnet.infura.io/v3/<your-key>',
25
+ host: 'mainnet.infura.io',
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,17 +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)
49
+ # @param [String] host The host to connect to
50
+ # @param [Integer] port TCP port to use
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
53
+ # @param [Boolean] ssl Should we use SSL (for https and wss)
54
+ # @param [String] proxy The URL of the proxy to use
44
55
  # @param [Object] log The destination for logs
45
- def initialize(contract: USDT, rpc: nil, wss: nil, chain: 1, log: $stdout)
56
+ def initialize(contract: USDT, chain: 1, log: $stdout,
57
+ host: nil, port: 443, http_path: '/', ws_path: '/',
58
+ ssl: true, proxy: nil)
46
59
  @contract = contract
47
- @rpc = rpc
48
- @wss = wss
60
+ @host = host
61
+ @port = port
62
+ @ssl = ssl
63
+ @http_path = http_path
64
+ @ws_path = ws_path
49
65
  @log = log
50
66
  @chain = chain
67
+ @proxy = proxy
51
68
  end
52
69
 
53
70
  # Get balance of a public address.
@@ -102,35 +119,39 @@ class ERC20::Wallet
102
119
 
103
120
  # Wait for incoming transactions and let the block know when they
104
121
  # arrive. It's a blocking call, it's better to run it in a separate
105
- # thread.
122
+ # thread. It will never finish. In order to stop it, you should do
123
+ # +Thread.kill+.
106
124
  #
107
125
  # @param [Array<String>] addresses Addresses to monitor
108
126
  # @param [Array] ready When connected, TRUE will be added to this array
109
127
  # @param [Boolean] raw TRUE if you need to get JSON events as they arrive from Websockets
110
128
  def accept(addresses, connected: [], raw: false)
111
- 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 } : {})
112
133
  log = @log
113
134
  contract = @contract
114
- wss = @wss
115
135
  ws.on(:open) do
116
- log.debug("Connected to #{wss}")
117
- msg = {
118
- jsonrpc: '2.0',
119
- id: 1,
120
- method: 'eth_subscribe',
121
- params: [
122
- 'logs',
123
- {
124
- address: contract,
125
- topics: [
126
- '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
127
- nil,
128
- addresses.map { |a| "0x000000000000000000000000#{a[2..]}" }
129
- ]
130
- }
131
- ]
132
- }
133
- 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
+ )
134
155
  connected.append(1)
135
156
  log.debug("Subscribed to #{addresses.count} addresses")
136
157
  end
@@ -155,19 +176,35 @@ class ERC20::Wallet
155
176
  end
156
177
  end
157
178
  ws.on(:close) do |_e|
158
- log.debug("Disconnected from #{wss}")
179
+ log.debug("Disconnected from #{@host}")
159
180
  end
160
181
  ws.on(:error) do |e|
161
- log.debug("Error at #{wss}: #{e}")
182
+ log.debug("Error at #{@host}: #{e.message}")
162
183
  end
163
184
  end
164
185
  end
165
186
 
166
187
  private
167
188
 
189
+ def url(http: true)
190
+ "#{http ? 'http' : 'ws'}#{@ssl ? 's' : ''}://#{@host}:#{@port}#{http ? @http_path : @ws_path}"
191
+ end
192
+
168
193
  def jsonrpc
169
194
  JSONRPC.logger = Loog::NULL
170
- 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:)
171
208
  end
172
209
 
173
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.3'
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,17 +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
- log: Loog::NULL
66
+ host: 'mainnet.infura.io',
67
+ http_path: '/v3/invalid-key-here',
68
+ log: loog
66
69
  )
67
- assert_raises(StandardError) { w.balance(STABLE_ADDRESS) }
70
+ assert_raises(StandardError) { w.balance(STABLE) }
68
71
  end
69
72
 
70
73
  def test_checks_balance_on_testnet
71
- skip('does not work')
72
- 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)
73
86
  refute_nil(b)
74
- assert_predicate(b, :positive?)
87
+ assert_predicate(b, :zero?)
75
88
  end
76
89
 
77
90
  def test_checks_balance_on_hardhat
@@ -105,7 +118,7 @@ class TestWallet < Minitest::Test
105
118
  event = e
106
119
  end
107
120
  rescue StandardError => e
108
- puts Backtrace.new(e)
121
+ loog.error(Backtrace.new(e))
109
122
  end
110
123
  wait_for { !connected.empty? }
111
124
  sum = 77_000
@@ -119,8 +132,80 @@ class TestWallet < Minitest::Test
119
132
  end
120
133
  end
121
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
+
122
203
  private
123
204
 
205
+ def loog
206
+ ENV['RAKE'] ? Loog::NULL : Loog::VERBOSE
207
+ end
208
+
124
209
  def wait_for
125
210
  start = Time.now
126
211
  loop do
@@ -144,29 +229,66 @@ class TestWallet < Minitest::Test
144
229
 
145
230
  def mainnet
146
231
  [
147
- "https://mainnet.infura.io/v3/#{env('INFURA_KEY')}",
148
- "https://go.getblock.io/#{env('GETBLOCK_KEY')}"
149
- ].map do |rpc|
150
- ERC20::Wallet.new(rpc:, 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)
151
244
  end.sample
152
245
  end
153
246
 
154
247
  def testnet
155
248
  [
156
- "https://sepolia.infura.io/v3/#{env('INFURA_KEY')}",
157
- "https://go.getblock.io/#{env('GETBLOCK_SEPOILA_KEY')}"
158
- ].map do |rpc|
159
- ERC20::Wallet.new(rpc:, 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)
160
261
  end.sample
161
262
  end
162
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
+
163
285
  def on_hardhat
164
286
  RandomPort::Pool::SINGLETON.acquire do |port|
165
287
  donce(
166
288
  home: File.join(__dir__, '../../hardhat'),
167
289
  ports: { port => 8545 },
168
290
  command: 'npx hardhat node',
169
- log: Loog::NULL
291
+ log: loog
170
292
  ) do
171
293
  wait_for_port(port)
172
294
  cmd = [
@@ -179,14 +301,13 @@ class TestWallet < Minitest::Test
179
301
  home: File.join(__dir__, '../../hardhat'),
180
302
  command: "/bin/bash -c #{Shellwords.escape(cmd)}",
181
303
  build_args: { 'HOST' => donce_host, 'PORT' => port },
182
- log: Loog::NULL,
304
+ log: loog,
183
305
  root: true
184
306
  ).split("\n").last
185
307
  wallet = ERC20::Wallet.new(
186
308
  contract:, chain: 4242,
187
- rpc: "http://localhost:#{port}",
188
- wss: "ws://localhost:#{port}",
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.3
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: []