erc20 0.2.9 → 0.4.0

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: bdb92899afb7e0f3ac74c59c07cdf1f48441d8b8bab6c96fadffe506c49dcedd
4
- data.tar.gz: fd0faec13d2aafdd1cbd02afd0066c17b308b96637469f60eca0cbd1d5102629
3
+ metadata.gz: aae427d3d4d3c935aa7ea204031b9bdd85c67ce26fd182cb3a3d4ac8c2ed3cd4
4
+ data.tar.gz: 54fce4882a54f7de725bcc40ca234538900dfa67bcae210b23544ac0806d31d9
5
5
  SHA512:
6
- metadata.gz: 509bdbaa8838f52ad6ea7d8a779001c1bfd87ba9c448ce4b808849967575069b8452e3a1f50b506c38f282b709e31e690a31b4247452b34d8cc097caa72e3b45
7
- data.tar.gz: 8fa48303af7a75dd4019062bb9d3904c84f76f16dd994ee95d3d6cb0f952c9e207030be9063781c3224af6d0a3cde0f107667cdd4447c9fdc4108a05725b3bc3
6
+ metadata.gz: 8d49f09b1f3210391496b670aa467455584ba1cce21a19b2247bd6874438291803aef1e367e78c8027e2b6e1eb174ff7950eb002ae46ef272dcc59381948c7c0
7
+ data.tar.gz: ea308190d652a2f7747e24f93910e8d4a2c593acbc01edd53d60594e56f96652591a49281d6f784873f46c2474e99385292554eea66eb3cb6a856efd24c6796e
data/Gemfile CHANGED
@@ -8,8 +8,9 @@ gemspec
8
8
 
9
9
  gem 'backtrace', '~>0.4', require: false
10
10
  gem 'concurrent-ruby', '~>1.2', require: false
11
- gem 'cucumber', '~>10.0', require: false
11
+ gem 'cucumber', '~>11.0', require: false
12
12
  gem 'donce', '~>0.2', require: false
13
+ gem 'em-websocket', '~>0.5', require: false
13
14
  gem 'faraday', '~>2.14', require: false
14
15
  gem 'loog', '~>0.6', require: false
15
16
  gem 'minitest', '~>6.0', require: false
@@ -18,13 +19,14 @@ gem 'minitest-retry', '~>0.2', require: false
18
19
  gem 'qbash', '~>0.4', require: false
19
20
  gem 'rake', '~>13.2', require: false
20
21
  gem 'random-port', '~>0.7', require: false
21
- gem 'rdoc', '~>7.0', require: false
22
+ gem 'rdoc', '~>8.0', require: false
22
23
  gem 'rubocop', '~>1.75', require: false
24
+ gem 'rubocop-elegant', '~>0.5', require: false
23
25
  gem 'rubocop-minitest', '~>0.38', require: false
24
26
  gem 'rubocop-performance', '~>1.25', require: false
25
27
  gem 'rubocop-rake', '~>0.7', require: false
26
- gem 'simplecov', '~>0.22', require: false
27
- gem 'simplecov-cobertura', '~>3.1', require: false
28
+ gem 'simplecov', '~>1.0', require: false
29
+ gem 'simplecov-cobertura', '~>4.0', require: false
28
30
  gem 'threads', '~>0.4', require: false
29
31
  gem 'typhoeus', '~>1.5', require: false
30
32
  gem 'webmock', '~>3.23', require: false
data/Gemfile.lock CHANGED
@@ -13,55 +13,57 @@ PATH
13
13
  GEM
14
14
  remote: https://rubygems.org/
15
15
  specs:
16
- addressable (2.8.8)
16
+ addressable (2.9.0)
17
17
  public_suffix (>= 2.0.2, < 8.0)
18
- ansi (1.5.0)
18
+ ansi (1.6.0)
19
19
  ast (2.4.3)
20
20
  backtrace (0.4.1)
21
21
  base64 (0.3.0)
22
- bigdecimal (4.0.1)
22
+ bigdecimal (4.1.2)
23
23
  builder (3.3.0)
24
- concurrent-ruby (1.3.6)
24
+ concurrent-ruby (1.3.8)
25
25
  crack (1.0.1)
26
26
  bigdecimal
27
27
  rexml
28
- cucumber (10.2.0)
28
+ cucumber (11.1.1)
29
29
  base64 (~> 0.2)
30
30
  builder (~> 3.2)
31
31
  cucumber-ci-environment (> 9, < 12)
32
- cucumber-core (> 15, < 17)
32
+ cucumber-core (>= 16.2.0, < 17)
33
33
  cucumber-cucumber-expressions (> 17, < 20)
34
- cucumber-html-formatter (> 21, < 23)
34
+ cucumber-html-formatter (> 21, < 24)
35
35
  diff-lcs (~> 1.5)
36
36
  logger (~> 1.6)
37
37
  mini_mime (~> 1.1)
38
38
  multi_test (~> 1.1)
39
- sys-uname (~> 1.3)
39
+ sys-uname (~> 1.5)
40
40
  cucumber-ci-environment (11.0.0)
41
- cucumber-core (16.1.1)
41
+ cucumber-core (16.2.0)
42
42
  cucumber-gherkin (> 36, < 40)
43
43
  cucumber-messages (> 31, < 33)
44
44
  cucumber-tag-expressions (> 6, < 9)
45
- cucumber-cucumber-expressions (19.0.0)
45
+ cucumber-cucumber-expressions (19.0.1)
46
46
  bigdecimal
47
- cucumber-gherkin (38.0.0)
47
+ cucumber-gherkin (39.1.0)
48
48
  cucumber-messages (>= 31, < 33)
49
- cucumber-html-formatter (22.3.0)
49
+ cucumber-html-formatter (23.1.0)
50
50
  cucumber-messages (> 23, < 33)
51
- cucumber-messages (32.0.1)
51
+ cucumber-messages (32.3.1)
52
52
  cucumber-tag-expressions (8.1.0)
53
- date (3.5.1)
54
53
  diff-lcs (1.6.2)
55
- docile (1.4.1)
56
- donce (0.4.0)
54
+ donce (0.7.0)
57
55
  backtrace (~> 0.3)
58
56
  os (~> 1.1)
59
57
  qbash (~> 0.3)
60
- elapsed (0.2.2)
58
+ drb (2.2.3)
59
+ elapsed (0.3.1)
61
60
  loog (~> 0.6)
62
61
  tago (~> 0.1)
63
62
  ellipsized (0.3.0)
64
- erb (6.0.1)
63
+ em-websocket (0.5.3)
64
+ eventmachine (>= 0.12.9)
65
+ http_parser.rb (~> 0)
66
+ erb (6.0.6)
65
67
  eth (0.5.13)
66
68
  forwardable (~> 1.3)
67
69
  keccak (~> 1.3)
@@ -69,102 +71,110 @@ GEM
69
71
  openssl (>= 2.2, < 4.0)
70
72
  rbsecp256k1 (~> 6.0)
71
73
  scrypt (~> 3.0)
72
- ethon (0.15.0)
74
+ ethon (0.18.0)
73
75
  ffi (>= 1.15.0)
76
+ logger
74
77
  eventmachine (1.2.7)
75
- faraday (2.14.0)
78
+ faraday (2.14.3)
76
79
  faraday-net_http (>= 2.0, < 3.5)
77
80
  json
78
81
  logger
79
- faraday-net_http (3.4.2)
82
+ faraday-net_http (3.4.4)
80
83
  net-http (~> 0.5)
81
84
  faye-websocket (0.12.0)
82
85
  eventmachine (>= 0.12.0)
83
86
  websocket-driver (>= 0.8.0)
84
- ffi (1.17.3-arm64-darwin)
85
- ffi (1.17.3-x64-mingw-ucrt)
86
- ffi (1.17.3-x86_64-darwin)
87
- ffi (1.17.3-x86_64-linux-gnu)
88
- ffi-compiler (1.3.2)
87
+ ffi (1.17.4-arm64-darwin)
88
+ ffi (1.17.4-x64-mingw-ucrt)
89
+ ffi (1.17.4-x86_64-darwin)
90
+ ffi (1.17.4-x86_64-linux-gnu)
91
+ ffi-compiler (1.4.2)
89
92
  ffi (>= 1.15.5)
90
93
  rake
91
94
  forwardable (1.4.0)
92
95
  hashdiff (1.2.1)
93
- json (2.18.0)
96
+ http_parser.rb (0.8.1)
97
+ json (2.21.1)
94
98
  jsonrpc-client (0.1.4)
95
99
  faraday
96
100
  multi_json (>= 1.1.0)
97
- keccak (1.3.2)
101
+ keccak (1.3.3)
98
102
  konstructor (1.0.2)
99
- language_server-protocol (3.17.0.5)
103
+ language_server-protocol (3.17.0.6)
100
104
  lint_roller (1.1.0)
101
105
  logger (1.7.0)
102
- loog (0.7.2)
106
+ loog (0.8.0)
103
107
  ellipsized
104
108
  logger (~> 1.0)
105
109
  memoist3 (1.0.0)
106
110
  mini_mime (1.1.5)
107
111
  mini_portile2 (2.8.9)
108
- minitest (6.0.1)
112
+ minitest (6.0.6)
113
+ drb (~> 2.0)
109
114
  prism (~> 1.5)
110
- minitest-reporters (1.7.1)
115
+ minitest-reporters (1.8.0)
111
116
  ansi
112
117
  builder
113
- minitest (>= 5.0)
118
+ minitest (>= 5.0, < 7)
114
119
  ruby-progressbar
115
120
  minitest-retry (0.3.1)
116
121
  minitest (>= 5.0)
117
- multi_json (1.19.1)
122
+ multi_json (1.21.1)
118
123
  multi_test (1.1.0)
119
124
  net-http (0.9.1)
120
125
  uri (>= 0.11.1)
121
- openssl (3.3.2)
126
+ openssl (3.3.3)
122
127
  os (1.1.4)
123
- parallel (1.27.0)
124
- parser (3.3.10.1)
128
+ parallel (2.1.0)
129
+ parser (3.3.12.0)
125
130
  ast (~> 2.4.1)
126
131
  racc
127
132
  pkg-config (1.6.5)
128
- prism (1.8.0)
129
- psych (5.3.1)
130
- date
131
- stringio
132
- public_suffix (7.0.2)
133
- qbash (0.6.0)
133
+ prism (1.9.0)
134
+ public_suffix (7.0.5)
135
+ qbash (0.8.4)
134
136
  backtrace (> 0)
135
137
  elapsed (> 0)
136
138
  loog (> 0)
137
139
  tago (> 0)
138
140
  racc (1.8.1)
139
141
  rainbow (3.1.1)
140
- rake (13.3.1)
141
- random-port (0.7.6)
142
+ rake (13.4.2)
143
+ random-port (0.8.2)
142
144
  tago (~> 0.0)
145
+ rbs (4.1.0)
146
+ logger
147
+ prism (>= 1.6.0)
148
+ tsort
143
149
  rbsecp256k1 (6.0.0)
144
150
  mini_portile2 (~> 2.8)
145
151
  pkg-config (~> 1.5)
146
152
  rubyzip (~> 2.3)
147
- rdoc (7.1.0)
153
+ rdoc (8.0.0)
148
154
  erb
149
- psych (>= 4.0.0)
155
+ prism (>= 1.6.0)
156
+ rbs (>= 4.0.0)
150
157
  tsort
151
- regexp_parser (2.11.3)
158
+ regexp_parser (2.12.0)
152
159
  rexml (3.4.4)
153
- rubocop (1.82.1)
160
+ rubocop (1.88.2)
154
161
  json (~> 2.3)
155
162
  language_server-protocol (~> 3.17.0.2)
156
163
  lint_roller (~> 1.1.0)
157
- parallel (~> 1.10)
164
+ parallel (>= 1.10)
158
165
  parser (>= 3.3.0.2)
159
166
  rainbow (>= 2.2.2, < 4.0)
160
167
  regexp_parser (>= 2.9.3, < 3.0)
161
- rubocop-ast (>= 1.48.0, < 2.0)
168
+ rubocop-ast (>= 1.49.0, < 2.0)
162
169
  ruby-progressbar (~> 1.7)
163
170
  unicode-display_width (>= 2.4.0, < 4.0)
164
- rubocop-ast (1.49.0)
171
+ rubocop-ast (1.50.0)
165
172
  parser (>= 3.3.7.2)
166
173
  prism (~> 1.7)
167
- rubocop-minitest (0.38.2)
174
+ rubocop-elegant (0.7.1)
175
+ lint_roller (~> 1.1)
176
+ rubocop (~> 1.75)
177
+ rubocop-minitest (0.40.0)
168
178
  lint_roller (~> 1.1)
169
179
  rubocop (>= 1.75.0, < 2.0)
170
180
  rubocop-ast (>= 1.38.0, < 2.0)
@@ -180,40 +190,39 @@ GEM
180
190
  scrypt (3.1.0)
181
191
  ffi-compiler (>= 1.0, < 2.0)
182
192
  rake (~> 13)
183
- simplecov (0.22.0)
184
- docile (~> 1.1)
185
- simplecov-html (~> 0.11)
186
- simplecov_json_formatter (~> 0.1)
187
- simplecov-cobertura (3.1.0)
193
+ simplecov (1.0.3)
194
+ simplecov-cobertura (4.0.0)
188
195
  rexml
189
- simplecov (~> 0.19)
190
- simplecov-html (0.13.2)
191
- simplecov_json_formatter (0.1.4)
192
- stringio (3.2.0)
193
- sys-uname (1.4.1)
196
+ simplecov (~> 1.0)
197
+ sys-uname (1.5.1)
198
+ ffi (~> 1.1)
199
+ memoist3 (~> 1.0.0)
200
+ sys-uname (1.5.1-universal-mingw32)
194
201
  ffi (~> 1.1)
195
202
  memoist3 (~> 1.0.0)
203
+ win32ole
196
204
  tago (0.7.0)
197
205
  thor (1.5.0)
198
206
  threads (0.5.0)
199
207
  backtrace (~> 0)
200
208
  concurrent-ruby (~> 1.0)
201
209
  tsort (0.2.0)
202
- typhoeus (1.5.0)
203
- ethon (>= 0.9.0, < 0.16.0)
210
+ typhoeus (1.6.0)
211
+ ethon (>= 0.18.0)
204
212
  unicode-display_width (3.2.0)
205
213
  unicode-emoji (~> 4.1)
206
214
  unicode-emoji (4.2.0)
207
215
  uri (1.1.1)
208
- webmock (3.26.1)
216
+ webmock (3.26.2)
209
217
  addressable (>= 2.8.0)
210
218
  crack (>= 0.3.2)
211
219
  hashdiff (>= 0.4.0, < 2.0.0)
212
- websocket-driver (0.8.0)
220
+ websocket-driver (0.8.2)
213
221
  base64
214
222
  websocket-extensions (>= 0.1.0)
215
223
  websocket-extensions (0.1.5)
216
- yard (0.9.38)
224
+ win32ole (1.9.3)
225
+ yard (0.9.45)
217
226
 
218
227
  PLATFORMS
219
228
  arm64-darwin-22
@@ -227,8 +236,9 @@ PLATFORMS
227
236
  DEPENDENCIES
228
237
  backtrace (~> 0.4)
229
238
  concurrent-ruby (~> 1.2)
230
- cucumber (~> 10.0)
239
+ cucumber (~> 11.0)
231
240
  donce (~> 0.2)
241
+ em-websocket (~> 0.5)
232
242
  erc20!
233
243
  faraday (~> 2.14)
234
244
  loog (~> 0.6)
@@ -238,13 +248,14 @@ DEPENDENCIES
238
248
  qbash (~> 0.4)
239
249
  rake (~> 13.2)
240
250
  random-port (~> 0.7)
241
- rdoc (~> 7.0)
251
+ rdoc (~> 8.0)
242
252
  rubocop (~> 1.75)
253
+ rubocop-elegant (~> 0.5)
243
254
  rubocop-minitest (~> 0.38)
244
255
  rubocop-performance (~> 1.25)
245
256
  rubocop-rake (~> 0.7)
246
- simplecov (~> 0.22)
247
- simplecov-cobertura (~> 3.1)
257
+ simplecov (~> 1.0)
258
+ simplecov-cobertura (~> 4.0)
248
259
  threads (~> 0.4)
249
260
  typhoeus (~> 1.5)
250
261
  webmock (~> 3.23)
data/README.md CHANGED
@@ -29,7 +29,7 @@ Or simply add this to your Gemfile:
29
29
  gem 'erc20'
30
30
  ```
31
31
 
32
- Then, make an instance of the main class and use to read
32
+ Then, make an instance of the main class and use it to read
33
33
  balances, send and receive payments:
34
34
 
35
35
  ```ruby
@@ -40,6 +40,8 @@ w = ERC20::Wallet.new(
40
40
  host: 'mainnet.infura.io',
41
41
  http_path: '/v3/<your-infura-key>',
42
42
  ws_path: '/ws/v3/<your-infura-key>',
43
+ attempts: 3, # try every endpoint up to 3 times, with backoff
44
+ fallbacks: ['https://eth.drpc.org'], # alternative RPC endpoints to try
43
45
  log: $stdout
44
46
  )
45
47
 
@@ -56,9 +58,16 @@ w.accept(addresses) do |event|
56
58
  puts event[:amount] # how much, in tokens (1000000 = $1 USDT)
57
59
  puts event[:from] # who sent the payment
58
60
  puts event[:to] # who was the receiver
61
+ puts event[:block] # number of the block it was mined in
62
+ puts event[:index] # position of the log in the block
59
63
  end
60
64
  ```
61
65
 
66
+ When the connection to the provider breaks, `accept` reconnects and fetches the
67
+ logs of the blocks that were mined while it was away. A payment may reach the
68
+ block twice because of that, so use `txn` and `index` together as the key of
69
+ the payment and credit it only once.
70
+
62
71
  You can also check ETH balance and send ETH transactions:
63
72
 
64
73
  ```ruby
@@ -75,8 +84,9 @@ To check the price of a gas unit and the expected cost of a payment:
75
84
  # How many gas units required to send this payment:
76
85
  units = w.gas_estimate(from, to, amount)
77
86
 
78
- # What is the price of a gas unit, in gwei:
79
- gwei = w.gas_price
87
+ # What is the most a gas unit may cost, in wei (payments are type-2,
88
+ # thus the network charges only the base fee plus the tip):
89
+ price = w.gas_price
80
90
  ```
81
91
 
82
92
  To generate a new private key, use [eth](https://rubygems.org/gems/eth):
@@ -106,7 +116,7 @@ w = ERC20::Wallet.new(
106
116
  You can use [squid-proxy] [Docker] image to set up your own [HTTP proxy] server.
107
117
 
108
118
  Of course, this library works with [Polygon], [Optimism],
109
- and other EVM compatible blockchains.
119
+ and other [EVM] compatible blockchains.
110
120
 
111
121
  ## How to use in command line
112
122
 
@@ -170,3 +180,4 @@ If it's clean and you don't see any error messages, submit your pull request.
170
180
  [Docker]: https://www.docker.com/
171
181
  [Polygon]: https://polygon.technology/
172
182
  [Optimism]: https://www.optimism.io/
183
+ [EVM]: https://ethereum.org/developers/docs/evm/
data/Rakefile CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rake'
4
+ require 'rake/clean'
3
5
  # SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
4
6
  # SPDX-License-Identifier: MIT
5
7
 
6
8
  require 'rubygems'
7
- require 'rake'
8
- require 'rake/clean'
9
9
 
10
10
  ENV['RAKE'] = 'true'
11
11
 
data/bin/erc20 CHANGED
@@ -43,7 +43,10 @@ class Bin < Thor
43
43
  class_option :proxy, type: :string,
44
44
  desc: 'HTTP/S proxy for all requests, e.g. "localhost:3128"'
45
45
  class_option :attempts, type: :numeric, default: 1,
46
- desc: 'How many times should we try before failing'
46
+ desc: 'How many times should we try every endpoint before failing'
47
+ class_option :fallbacks, type: :array,
48
+ default: ['https://ethereum.publicnode.com', 'https://eth.drpc.org', 'https://rpc.ankr.com/eth'],
49
+ desc: 'Fallback HTTP RPC endpoint URLs to try when the primary host fails'
47
50
  class_option :dry, type: :boolean, default: false,
48
51
  desc: "Don't send a real payment, run in a read-only mode"
49
52
  class_option :verbose, type: :boolean, default: false,
@@ -136,6 +139,8 @@ class Bin < Thor
136
139
  host: options[:host], port: options[:port].to_i,
137
140
  http_path: options[:http_path], ws_path: options[:ws_path],
138
141
  ssl: options[:ssl],
142
+ attempts: options[:attempts].to_i,
143
+ fallbacks: options[:fallbacks],
139
144
  log: log
140
145
  )
141
146
  end
@@ -146,10 +151,10 @@ class Bin < Thor
146
151
  amount = amount.to_i
147
152
  log.debug("The token amount equals to #{amount} ERC20 tokens (as provided)")
148
153
  elsif /^[0-9]+(\.[0-9]+)?usdt$/.match?(amount)
149
- amount = (amount.gsub(/usdt$/, '').to_f * 1_000_000).to_i
154
+ amount = units(amount.gsub(/usdt$/, ''), 1_000_000)
150
155
  log.debug("The USDT amount equals to #{amount} ERC20 tokens")
151
156
  elsif /^\$[0-9]+(\.[0-9]+)?$/.match?(amount)
152
- amount = (amount.gsub(/^\$/, '').to_f * 1_000_000).to_i
157
+ amount = units(amount.gsub(/^\$/, ''), 1_000_000)
153
158
  log.debug("The dollar amount equals to #{amount} ERC20 tokens")
154
159
  else
155
160
  raise "Can't understand amount: #{amount.inspect}"
@@ -160,16 +165,24 @@ class Bin < Thor
160
165
  def wei(amount)
161
166
  if /^[0-9]+$/.match?(amount)
162
167
  amount.to_i
163
- elsif /[0-9]wei$/.match?(amount)
168
+ elsif /^[0-9]+wei$/.match?(amount)
164
169
  amount.gsub(/wei$/, '').to_i
165
- elsif /[0-9]gwei$/.match?(amount)
166
- (amount.gsub(/gwei$/, '').to_f * 1_000_000_000).to_i
167
- elsif /[0-9]eth$/.match?(amount)
168
- (amount.gsub(/eth$/, '').to_f * 1_000_000_000_000_000_000).to_i
170
+ elsif /^[0-9]+(\.[0-9]+)?gwei$/.match?(amount)
171
+ units(amount.gsub(/gwei$/, ''), 1_000_000_000)
172
+ elsif /^[0-9]+(\.[0-9]+)?eth$/.match?(amount)
173
+ units(amount.gsub(/eth$/, ''), 1_000_000_000_000_000_000)
169
174
  else
170
175
  raise "Can't understand amount: #{amount.inspect}"
171
176
  end
172
177
  end
178
+
179
+ def units(amount, factor)
180
+ exact = Rational(amount) * factor
181
+ unless exact.denominator == 1
182
+ raise "Amount #{amount.inspect} is too precise, while the smallest unit is 1/#{factor}"
183
+ end
184
+ exact.numerator
185
+ end
173
186
  end
174
187
 
175
188
  begin
data/erc20.gemspec CHANGED
@@ -7,7 +7,7 @@ require 'English'
7
7
  require_relative 'lib/erc20/erc20'
8
8
 
9
9
  Gem::Specification.new do |s|
10
- s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to?(:required_rubygems_version=)
11
11
  s.required_ruby_version = '~>3.0'
12
12
  s.name = 'erc20'
13
13
  s.version = ERC20::VERSION
@@ -25,12 +25,12 @@ Gem::Specification.new do |s|
25
25
  s.rdoc_options = ['--charset=UTF-8']
26
26
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
27
27
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
28
- s.add_dependency 'elapsed', '~>0.2'
29
- s.add_dependency 'eth', '~>0.5'
30
- s.add_dependency 'faye-websocket', '~>0.11'
31
- s.add_dependency 'json', '~>2.10'
32
- s.add_dependency 'jsonrpc-client', '~>0.1'
33
- s.add_dependency 'loog', '~>0.4'
34
- s.add_dependency 'thor', '~>1.3'
28
+ s.add_dependency('elapsed', '~>0.2')
29
+ s.add_dependency('eth', '~>0.5')
30
+ s.add_dependency('faye-websocket', '~>0.11')
31
+ s.add_dependency('json', '~>2.10')
32
+ s.add_dependency('jsonrpc-client', '~>0.1')
33
+ s.add_dependency('loog', '~>0.4')
34
+ s.add_dependency('thor', '~>1.3')
35
35
  s.metadata['rubygems_mfa_required'] = 'true'
36
36
  end
data/features/dry.feature CHANGED
@@ -21,13 +21,17 @@ Feature: Command Line Processing, in Dry Mode
21
21
  Then Exit code is zero
22
22
 
23
23
  Scenario: ERC20 payment can be sent in dollars
24
- When I run bin/erc20 with "pay --dry --verbose 46feba063e9b59a8ae0dba68abd39a3cb8f52089e776576d6eb1bb5bfec123d1 0x7232148927F8a580053792f44D4d59d40Fd00ABD $10"
24
+ When I run bin/erc20 with "pay --dry --verbose 46feba063e9b59a8ae0dba68abd39a3cb8f52089e776576d6eb1bb5bfec123d1 0x7232148927F8a580053792f44D4d59d40Fd00ABD \$10"
25
25
  Then Exit code is zero
26
26
 
27
27
  Scenario: ERC20 payment can be sent in USDT
28
28
  When I run bin/erc20 with "pay --dry --verbose 46feba063e9b59a8ae0dba68abd39a3cb8f52089e776576d6eb1bb5bfec123d1 0x7232148927F8a580053792f44D4d59d40Fd00ABD 10usdt"
29
29
  Then Exit code is zero
30
30
 
31
+ Scenario: ERC20 payment in USDT keeps every token unit
32
+ When I run bin/erc20 with "pay --dry --verbose 46feba063e9b59a8ae0dba68abd39a3cb8f52089e776576d6eb1bb5bfec123d1 0x7232148927F8a580053792f44D4d59d40Fd00ABD 8.2usdt"
33
+ Then Stdout contains "Sending 8200000 ERC20 tokens"
34
+
31
35
  Scenario: ETH payment can be sent in wei
32
36
  When I run bin/erc20 with "eth_pay --dry --verbose 46feba063e9b59a8ae0dba68abd39a3cb8f52089e776576d6eb1bb5bfec123d1 0x7232148927F8a580053792f44D4d59d40Fd00ABD 10000000"
33
37
  Then Exit code is zero
@@ -35,3 +39,7 @@ Feature: Command Line Processing, in Dry Mode
35
39
  Scenario: ETH payment can be sent in ETH
36
40
  When I run bin/erc20 with "eth_pay --dry --verbose 46feba063e9b59a8ae0dba68abd39a3cb8f52089e776576d6eb1bb5bfec123d1 0x7232148927F8a580053792f44D4d59d40Fd00ABD 1eth"
37
41
  Then Exit code is zero
42
+
43
+ Scenario: ETH payment smaller than one wei is rejected
44
+ When I run bin/erc20 with "eth_pay --dry 46feba063e9b59a8ae0dba68abd39a3cb8f52089e776576d6eb1bb5bfec123d1 0x7232148927F8a580053792f44D4d59d40Fd00ABD 0.0000000000000000001eth"
45
+ Then Exit code is not zero
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'English'
3
4
  # SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
4
5
  # SPDX-License-Identifier: MIT
5
6
 
6
7
  require 'tmpdir'
7
- require 'English'
8
8
  require_relative '../../lib/erc20'
9
9
 
10
10
  Before do
@@ -31,19 +31,19 @@ When(%r{^I run bin/erc20 with "([^"]*)"$}) do |arg|
31
31
  end
32
32
 
33
33
  Then(/^Stdout contains "([^"]*)"$/) do |txt|
34
- raise "STDOUT doesn't contain '#{txt}':\n#{@stdout}" unless @stdout.include?(txt)
34
+ raise(StandardError, "STDOUT doesn't contain '#{txt}':\n#{@stdout}") unless @stdout.include?(txt)
35
35
  end
36
36
 
37
37
  Then(/^Stdout is empty$/) do
38
- raise "STDOUT is not empty:\n#{@stdout}" unless @stdout == ''
38
+ raise(StandardError, "STDOUT is not empty:\n#{@stdout}") unless @stdout == ''
39
39
  end
40
40
 
41
41
  Then(/^Exit code is zero$/) do
42
- raise "Non-zero exit #{@exitstatus}:\n#{@stdout}" unless @exitstatus.zero?
42
+ raise(StandardError, "Non-zero exit #{@exitstatus}:\n#{@stdout}") unless @exitstatus.zero?
43
43
  end
44
44
 
45
45
  Then(/^Exit code is not zero$/) do
46
- raise 'Zero exit code' if @exitstatus.zero?
46
+ raise(StandardError, 'Zero exit code') if @exitstatus.zero?
47
47
  end
48
48
 
49
49
  When(/^I run bash with "([^"]*)"$/) do |text|
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'cucumber'
3
4
  # SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
4
5
  # SPDX-License-Identifier: MIT
5
6
 
6
7
  require 'simplecov'
7
- require 'cucumber'
8
8
  require_relative '../../lib/erc20'