erc20 0.0.21 → 0.1.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 +4 -4
- data/.github/workflows/shellcheck.yml +0 -2
- data/.gitignore +1 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +33 -1
- data/README.md +20 -0
- data/REUSE.toml +13 -1
- data/Rakefile +9 -1
- data/bin/erc20 +152 -0
- data/erc20.gemspec +2 -0
- data/features/cli.feature +30 -0
- data/features/gem_package.feature +27 -0
- data/features/step_definitions/steps.rb +72 -0
- data/features/support/env.rb +8 -0
- data/lib/erc20/erc20.rb +1 -1
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c869348131d5d5bcb38966bc1eaac3d3e9655b11d6846f7ca9bc54893fb68458
|
4
|
+
data.tar.gz: 625b971154f40e09a8fd66091d154df5657efc4dee202bf3a5db3cc62c7e2a54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30abb7a895214f536f1c91ad6758b023ded4d28be61265c1db9576a60e71e3b3737b7c86157ba314d649b4096dd86b93936920d8c8a0d76ded554c86da69d931
|
7
|
+
data.tar.gz: 39083d6adc8e2eed75a7d548c2ae4a8311fc226199f2f6c679f23012945a31b2458a766278cb028fd7754d5c95975b2bbde7afbeb1342591cc1f3bf5d8b4f69e
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -7,6 +7,7 @@ PATH
|
|
7
7
|
json (>= 2.10.1)
|
8
8
|
jsonrpc-client (>= 0.1.4)
|
9
9
|
loog (> 0)
|
10
|
+
slop (> 4)
|
10
11
|
|
11
12
|
GEM
|
12
13
|
remote: https://rubygems.org/
|
@@ -50,6 +51,31 @@ GEM
|
|
50
51
|
concurrent-ruby (1.3.5)
|
51
52
|
connection_pool (2.5.0)
|
52
53
|
crass (1.0.6)
|
54
|
+
cucumber (9.1.2)
|
55
|
+
builder (~> 3.2, >= 3.2.4)
|
56
|
+
cucumber-ci-environment (~> 9.2, >= 9.2.0)
|
57
|
+
cucumber-core (~> 12.0)
|
58
|
+
cucumber-cucumber-expressions (~> 17.0)
|
59
|
+
cucumber-gherkin (> 24, < 27)
|
60
|
+
cucumber-html-formatter (> 20.3, < 22)
|
61
|
+
cucumber-messages (> 19, < 25)
|
62
|
+
diff-lcs (~> 1.5)
|
63
|
+
mini_mime (~> 1.1, >= 1.1.5)
|
64
|
+
multi_test (~> 1.1, >= 1.1.0)
|
65
|
+
sys-uname (~> 1.2, >= 1.2.3)
|
66
|
+
cucumber-ci-environment (9.2.0)
|
67
|
+
cucumber-core (12.0.0)
|
68
|
+
cucumber-gherkin (>= 25, < 27)
|
69
|
+
cucumber-messages (>= 20, < 23)
|
70
|
+
cucumber-tag-expressions (~> 5.0, >= 5.0.4)
|
71
|
+
cucumber-cucumber-expressions (17.1.0)
|
72
|
+
bigdecimal
|
73
|
+
cucumber-gherkin (26.2.0)
|
74
|
+
cucumber-messages (>= 19.1.4, < 22.1)
|
75
|
+
cucumber-html-formatter (21.9.0)
|
76
|
+
cucumber-messages (> 19, < 28)
|
77
|
+
cucumber-messages (22.0.0)
|
78
|
+
cucumber-tag-expressions (5.0.6)
|
53
79
|
date (3.4.1)
|
54
80
|
diff-lcs (1.6.0)
|
55
81
|
docile (1.4.1)
|
@@ -109,6 +135,7 @@ GEM
|
|
109
135
|
crass (~> 1.0.2)
|
110
136
|
nokogiri (>= 1.12.0)
|
111
137
|
loog (0.6.0)
|
138
|
+
mini_mime (1.1.5)
|
112
139
|
mini_portile2 (2.8.8)
|
113
140
|
minitest (5.25.4)
|
114
141
|
minitest-reporters (1.7.1)
|
@@ -119,6 +146,7 @@ GEM
|
|
119
146
|
minitest-retry (0.2.5)
|
120
147
|
minitest (>= 5.0)
|
121
148
|
multi_json (1.15.0)
|
149
|
+
multi_test (1.1.0)
|
122
150
|
net-http (0.6.0)
|
123
151
|
uri
|
124
152
|
nokogiri (1.18.3-arm64-darwin)
|
@@ -244,7 +272,10 @@ GEM
|
|
244
272
|
simplecov (~> 0.19)
|
245
273
|
simplecov-html (0.13.1)
|
246
274
|
simplecov_json_formatter (0.1.4)
|
247
|
-
|
275
|
+
slop (4.10.1)
|
276
|
+
stringio (3.1.5)
|
277
|
+
sys-uname (1.3.1)
|
278
|
+
ffi (~> 1.1)
|
248
279
|
tago (0.0.2)
|
249
280
|
thor (1.3.2)
|
250
281
|
threads (0.4.1)
|
@@ -277,6 +308,7 @@ PLATFORMS
|
|
277
308
|
|
278
309
|
DEPENDENCIES
|
279
310
|
backtrace (> 0)
|
311
|
+
cucumber (= 9.1.2)
|
280
312
|
donce (> 0)
|
281
313
|
erc20!
|
282
314
|
faraday (> 0)
|
data/README.md
CHANGED
@@ -93,6 +93,25 @@ You can use [squid-proxy] [Docker] image to set up your own [HTTP proxy] server.
|
|
93
93
|
Of course, this library works with [Polygon], [Optimism],
|
94
94
|
and other forks of [Etherium].
|
95
95
|
|
96
|
+
## How to use in command line
|
97
|
+
|
98
|
+
This gem also provides a command line tool for sending ETH and ERC20 payments
|
99
|
+
and checking balances.
|
100
|
+
|
101
|
+
First, you install it, via [gem]:
|
102
|
+
|
103
|
+
```bash
|
104
|
+
gem install erc20
|
105
|
+
```
|
106
|
+
|
107
|
+
Then, run it:
|
108
|
+
|
109
|
+
```bash
|
110
|
+
erc20 --help
|
111
|
+
```
|
112
|
+
|
113
|
+
It should be obvious how to use it. If not, please, submit an issue.
|
114
|
+
|
96
115
|
## How to use in tests
|
97
116
|
|
98
117
|
You can use `ERC20::FakeWallet` class that behaves exactly like
|
@@ -122,6 +141,7 @@ bundle exec rake
|
|
122
141
|
|
123
142
|
If it's clean and you don't see any error messages, submit your pull request.
|
124
143
|
|
144
|
+
[gem]: https://github.com/rubygems/rubygems
|
125
145
|
[Etherium]: https://en.wikipedia.org/wiki/Ethereum
|
126
146
|
[ERC20]: https://ethereum.org/en/developers/docs/standards/tokens/erc-20/
|
127
147
|
[JSON-RPC]: https://ethereum.org/en/developers/docs/apis/json-rpc/
|
data/REUSE.toml
CHANGED
@@ -4,15 +4,27 @@
|
|
4
4
|
version = 1
|
5
5
|
[[annotations]]
|
6
6
|
path = [
|
7
|
+
"**/*.csv",
|
8
|
+
"**/*.jpg",
|
9
|
+
"**/*.json",
|
10
|
+
"**/*.md",
|
11
|
+
"**/*.pdf",
|
12
|
+
"**/*.png",
|
13
|
+
"**/*.svg",
|
14
|
+
"**/*.txt",
|
15
|
+
"**/*.vm",
|
16
|
+
"**/.gitignore",
|
17
|
+
"**/CNAME",
|
7
18
|
".gitattributes",
|
8
19
|
".gitignore",
|
9
20
|
".gitleaksignore",
|
10
21
|
".pdd",
|
22
|
+
".xcop",
|
11
23
|
"Gemfile.lock",
|
12
24
|
"README.md",
|
13
25
|
"hardhat/.gitignore",
|
14
26
|
"hardhat/package.json",
|
15
|
-
"renovate.json"
|
27
|
+
"renovate.json",
|
16
28
|
]
|
17
29
|
precedence = "override"
|
18
30
|
SPDX-FileCopyrightText = "Copyright (c) 2025 Yegor Bugayenko"
|
data/Rakefile
CHANGED
@@ -17,7 +17,7 @@ def version
|
|
17
17
|
Gem::Specification.load(Dir['*.gemspec'].first).version
|
18
18
|
end
|
19
19
|
|
20
|
-
task default: %i[clean test rubocop yard]
|
20
|
+
task default: %i[clean test features rubocop yard]
|
21
21
|
|
22
22
|
require 'rake/testtask'
|
23
23
|
desc 'Run all unit tests'
|
@@ -42,6 +42,14 @@ RuboCop::RakeTask.new(:rubocop) do |task|
|
|
42
42
|
task.requires << 'rubocop-rspec'
|
43
43
|
end
|
44
44
|
|
45
|
+
require 'cucumber/rake/task'
|
46
|
+
Cucumber::Rake::Task.new(:features) do
|
47
|
+
Rake::Cleaner.cleanup_files(['coverage'])
|
48
|
+
end
|
49
|
+
Cucumber::Rake::Task.new(:'features:html') do |t|
|
50
|
+
t.profile = 'html_report'
|
51
|
+
end
|
52
|
+
|
45
53
|
desc 'Run benchmark script'
|
46
54
|
task :benchmark do
|
47
55
|
ruby 'benchmarks/simple.rb'
|
data/bin/erc20
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
|
5
|
+
# SPDX-License-Identifier: MIT
|
6
|
+
|
7
|
+
$stdout.sync = true
|
8
|
+
|
9
|
+
require 'backtrace'
|
10
|
+
require 'loog'
|
11
|
+
require 'slop'
|
12
|
+
require_relative '../lib/erc20'
|
13
|
+
require_relative '../lib/erc20/erc20'
|
14
|
+
require_relative '../lib/erc20/wallet'
|
15
|
+
|
16
|
+
begin
|
17
|
+
begin
|
18
|
+
opts = Slop.parse(ARGV, strict: true, help: true) do |o|
|
19
|
+
o.banner = "Usage (#{ERC20::VERSION}): erc20 [options] command [args]
|
20
|
+
Commands are:
|
21
|
+
key: Generate a new Etherium private key (64 symbols)
|
22
|
+
address: Turn private key into a public address (44 symbols)
|
23
|
+
price: Get current price of one gas unit, in gwei
|
24
|
+
pay: Send ERC20 payment
|
25
|
+
eth_pay: Send ETH payment
|
26
|
+
balance: Get ERC20 balance
|
27
|
+
eth_balance: Get ETH balance
|
28
|
+
Options are:"
|
29
|
+
o.string(
|
30
|
+
'--contract',
|
31
|
+
'Public address of ERC20 contract',
|
32
|
+
default: ERC20::Wallet::USDT
|
33
|
+
)
|
34
|
+
o.integer(
|
35
|
+
'--chain',
|
36
|
+
'Etherium chain ID',
|
37
|
+
default: 1
|
38
|
+
)
|
39
|
+
o.string(
|
40
|
+
'--host',
|
41
|
+
'Host name of the provider',
|
42
|
+
default: 'eth.llamarpc.com'
|
43
|
+
)
|
44
|
+
o.string(
|
45
|
+
'--port',
|
46
|
+
'TCP port of the provider',
|
47
|
+
default: 443
|
48
|
+
)
|
49
|
+
o.string(
|
50
|
+
'--http_path',
|
51
|
+
'URL path for the HTTP RPC entry point of the provider',
|
52
|
+
default: '/'
|
53
|
+
)
|
54
|
+
o.string(
|
55
|
+
'--ws_path',
|
56
|
+
'URL path for the Websockets entry point of the provider',
|
57
|
+
default: '/'
|
58
|
+
)
|
59
|
+
o.string(
|
60
|
+
'--proxy',
|
61
|
+
'HTTP/S proxy for all requests, e.g. "localhost:3128"'
|
62
|
+
)
|
63
|
+
o.integer(
|
64
|
+
'--attempts',
|
65
|
+
'How many times should we try before failing',
|
66
|
+
default: 1
|
67
|
+
)
|
68
|
+
o.bool(
|
69
|
+
'--dry',
|
70
|
+
'Don\'t send a real payment, run in a read-only mode'
|
71
|
+
)
|
72
|
+
o.bool('--help', 'Read this: https://github.com/yegor256/erc20') do
|
73
|
+
puts o
|
74
|
+
exit
|
75
|
+
end
|
76
|
+
o.bool('--verbose', 'Print all possible debug messages')
|
77
|
+
end
|
78
|
+
rescue Slop::Error => e
|
79
|
+
raise e.message
|
80
|
+
end
|
81
|
+
raise 'Try --help' if opts.arguments.empty?
|
82
|
+
log = opts[:verbose] ? Loog::VERBOSE : Loog::REGULAR
|
83
|
+
wallet = ERC20::Wallet.new(
|
84
|
+
contract: opts[:contract],
|
85
|
+
host: opts[:host], port: opts[:port],
|
86
|
+
http_path: opts[:http_path], ws_path: opts[:ws_path],
|
87
|
+
log:
|
88
|
+
)
|
89
|
+
case opts.arguments[0]
|
90
|
+
when 'key'
|
91
|
+
puts Eth::Key.new.private_hex
|
92
|
+
when 'address'
|
93
|
+
puts Eth::Key.new(priv: opts.arguments[1]).address.to_s
|
94
|
+
when 'price'
|
95
|
+
puts wallet.gas_price
|
96
|
+
when 'balance'
|
97
|
+
address = opts.arguments[1]
|
98
|
+
raise 'Address is required' if address.nil?
|
99
|
+
log.debug("Checking ERC20 balance of #{address}")
|
100
|
+
tokens = wallet.balance(address)
|
101
|
+
log.debug("The balance is #{tokens} ERC20 tokens (#{tokens.to_f / 1_000_000} USDT)")
|
102
|
+
puts tokens
|
103
|
+
when 'eth_balance'
|
104
|
+
address = opts.arguments[1]
|
105
|
+
raise 'Address is required' if address.nil?
|
106
|
+
log.debug("Checking ETH balance of #{address}")
|
107
|
+
wei = wallet.eth_balance(address)
|
108
|
+
log.debug("The balance of #{address} is #{wei} wei (#{format('%0.4f', wei.to_f / 1_000_000_000_000_000_000)} ETH)")
|
109
|
+
puts wei
|
110
|
+
when 'pay'
|
111
|
+
pkey = opts.arguments[1]
|
112
|
+
raise 'Private key is required' if pkey.nil?
|
113
|
+
priv = Eth::Key.new(priv: pkey)
|
114
|
+
log.debug("Sending ERC20 tokens from #{priv.address.to_s}")
|
115
|
+
address = opts.arguments[2]
|
116
|
+
raise 'Address is required' if address.nil?
|
117
|
+
log.debug("Sending ERC20 tokens to #{address}")
|
118
|
+
amount = opts.arguments[3]
|
119
|
+
raise 'Amount argument is required' if amount.nil?
|
120
|
+
raise 'Amount is not valid' unless /^[0-9]+(usdt)?$/.match?(amount)
|
121
|
+
amount = amount.to_i if /^[0-9]+$/.match?(amount)
|
122
|
+
amount = (amount.gsub(/usdt^/, '').to_f * 1_000_000).to_i if /^[0-9]usdt+$/.match?(amount)
|
123
|
+
log.debug("Sending #{amount} ERC20 tokens")
|
124
|
+
puts wallet.pay(priv.private_hex, address, amount)
|
125
|
+
when 'eth_pay'
|
126
|
+
pkey = opts.arguments[1]
|
127
|
+
raise 'Private key is required' if pkey.nil?
|
128
|
+
priv = Eth::Key.new(priv: pkey)
|
129
|
+
log.debug("Sending ETH from #{priv.address.to_s}")
|
130
|
+
address = opts.arguments[2]
|
131
|
+
raise 'Address is required' if address.nil?
|
132
|
+
log.debug("Sending ETH to #{address}")
|
133
|
+
amount = opts.arguments[3]
|
134
|
+
raise 'Amount argument is required' if amount.nil?
|
135
|
+
raise "Amount #{amount.inspect} is not valid" unless /^[0-9]+(\.[0-9]+)?(eth|wei|gwei)?$/.match?(amount)
|
136
|
+
amount = amount.to_i if /^[0-9]+$/.match?(amount)
|
137
|
+
amount = amount.gsub(/wei^/, '').to_i if /[0-9]wei+$/.match?(amount)
|
138
|
+
amount = (amount.gsub(/gwei^/, '').to_f * 1_000_000_000).to_i if /[0-9]gwei+$/.match?(amount)
|
139
|
+
amount = (amount.gsub(/eth^/, '').to_f * 1_000_000_000_000_000_000).to_i if /[0-9]eth+$/.match?(amount)
|
140
|
+
log.debug("Sending #{amount} wei...")
|
141
|
+
puts wallet.eth_pay(priv.private_hex, address, amount)
|
142
|
+
else
|
143
|
+
raise "Command #{opts.arguments[0]} is not supported"
|
144
|
+
end
|
145
|
+
rescue StandardError => e
|
146
|
+
if opts[:verbose]
|
147
|
+
puts Backtrace.new(e)
|
148
|
+
else
|
149
|
+
puts "ERROR: #{e.message}"
|
150
|
+
end
|
151
|
+
exit(255)
|
152
|
+
end
|
data/erc20.gemspec
CHANGED
@@ -23,11 +23,13 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.homepage = 'http://github.com/yegor256/erc20.rb'
|
24
24
|
s.files = `git ls-files`.split($RS)
|
25
25
|
s.rdoc_options = ['--charset=UTF-8']
|
26
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
26
27
|
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
27
28
|
s.add_dependency 'eth', '>=0.5.13'
|
28
29
|
s.add_dependency 'faye-websocket', '>=0.11.3'
|
29
30
|
s.add_dependency 'json', '>=2.10.1'
|
30
31
|
s.add_dependency 'jsonrpc-client', '>=0.1.4'
|
31
32
|
s.add_dependency 'loog', '>0'
|
33
|
+
s.add_dependency 'slop', '>4'
|
32
34
|
s.metadata['rubygems_mfa_required'] = 'true'
|
33
35
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
|
2
|
+
# SPDX-License-Identifier: MIT
|
3
|
+
|
4
|
+
Feature: Command Line Processing
|
5
|
+
As a simple ETH/ERC20 user I want to send payments
|
6
|
+
|
7
|
+
Scenario: Help can be printed
|
8
|
+
When I run bin/erc20 with "--help"
|
9
|
+
Then Exit code is zero
|
10
|
+
And Stdout contains "--help"
|
11
|
+
|
12
|
+
Scenario: Gas price price can be retrieved
|
13
|
+
When I run bin/erc20 with "price --attempts=4"
|
14
|
+
Then Exit code is zero
|
15
|
+
|
16
|
+
Scenario: ETH private key can be generated
|
17
|
+
When I run bin/erc20 with "key"
|
18
|
+
Then Exit code is zero
|
19
|
+
|
20
|
+
Scenario: ETH address can be created
|
21
|
+
When I run bin/erc20 with "address 46feba063e9b59a8ae0dba68abd39a3cb8f52089e776576d6eb1bb5bfec123d1"
|
22
|
+
Then Exit code is zero
|
23
|
+
|
24
|
+
Scenario: ERC20 balance can be checked
|
25
|
+
When I run bin/erc20 with "balance 0x7232148927F8a580053792f44D4d59d40Fd00ABD --verbose"
|
26
|
+
Then Exit code is zero
|
27
|
+
|
28
|
+
Scenario: ETH balance can be checked
|
29
|
+
When I run bin/erc20 with "eth_balance 0x7232148927F8a580053792f44D4d59d40Fd00ABD --verbose"
|
30
|
+
Then Exit code is zero
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
|
2
|
+
# SPDX-License-Identifier: MIT
|
3
|
+
|
4
|
+
Feature: Gem Package
|
5
|
+
As a source code writer I want to be able to
|
6
|
+
package the Gem into .gem file
|
7
|
+
|
8
|
+
Scenario: Gem can be packaged
|
9
|
+
Given It is Unix
|
10
|
+
Given I have a "execs.rb" file with content:
|
11
|
+
"""
|
12
|
+
#!/usr/bin/env ruby
|
13
|
+
require 'rubygems'
|
14
|
+
spec = Gem::Specification::load('./spec.rb')
|
15
|
+
if spec.executables.empty?
|
16
|
+
fail 'no executables: ' + File.read('./spec.rb')
|
17
|
+
end
|
18
|
+
"""
|
19
|
+
When I run bash with:
|
20
|
+
"""
|
21
|
+
cd erc20
|
22
|
+
gem build erc20.gemspec
|
23
|
+
gem specification --ruby erc20-*.gem > ../spec.rb
|
24
|
+
cd ..
|
25
|
+
ruby execs.rb
|
26
|
+
"""
|
27
|
+
Then Exit code is zero
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
|
4
|
+
# SPDX-License-Identifier: MIT
|
5
|
+
|
6
|
+
require 'tmpdir'
|
7
|
+
require 'slop'
|
8
|
+
require 'English'
|
9
|
+
require_relative '../../lib/erc20'
|
10
|
+
|
11
|
+
Before do
|
12
|
+
@cwd = Dir.pwd
|
13
|
+
@dir = Dir.mktmpdir('test')
|
14
|
+
FileUtils.mkdir_p(@dir)
|
15
|
+
Dir.chdir(@dir)
|
16
|
+
@opts =
|
17
|
+
Slop.parse ['-v'] do |o|
|
18
|
+
o.bool '-v', '--verbose'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
After do
|
23
|
+
Dir.chdir(@cwd)
|
24
|
+
FileUtils.rm_rf(@dir)
|
25
|
+
end
|
26
|
+
|
27
|
+
Given(/^I have a "([^"]*)" file with content:$/) do |file, text|
|
28
|
+
FileUtils.mkdir_p(File.dirname(file)) unless File.exist?(file)
|
29
|
+
File.write(file, text.gsub('\\xFF', 0xFF.chr))
|
30
|
+
end
|
31
|
+
|
32
|
+
When(%r{^I run bin/erc20 with "([^"]*)"$}) do |arg|
|
33
|
+
home = File.join(File.dirname(__FILE__), '../..')
|
34
|
+
@stdout = `ruby -I#{home}/lib #{home}/bin/erc20 #{arg}`
|
35
|
+
@exitstatus = $CHILD_STATUS.exitstatus
|
36
|
+
end
|
37
|
+
|
38
|
+
Then(/^Stdout contains "([^"]*)"$/) do |txt|
|
39
|
+
raise "STDOUT doesn't contain '#{txt}':\n#{@stdout}" unless @stdout.include?(txt)
|
40
|
+
end
|
41
|
+
|
42
|
+
Then(/^Stdout is empty$/) do
|
43
|
+
raise "STDOUT is not empty:\n#{@stdout}" unless @stdout == ''
|
44
|
+
end
|
45
|
+
|
46
|
+
Then(/^Exit code is zero$/) do
|
47
|
+
raise "Non-zero exit #{@exitstatus}:\n#{@stdout}" unless @exitstatus.zero?
|
48
|
+
end
|
49
|
+
|
50
|
+
Then(/^Exit code is not zero$/) do
|
51
|
+
raise 'Zero exit code' if @exitstatus.zero?
|
52
|
+
end
|
53
|
+
|
54
|
+
When(/^I run bash with "([^"]*)"$/) do |text|
|
55
|
+
FileUtils.copy_entry(@cwd, File.join(@dir, 'erc20'))
|
56
|
+
@stdout = `#{text}`
|
57
|
+
@exitstatus = $CHILD_STATUS.exitstatus
|
58
|
+
end
|
59
|
+
|
60
|
+
When(/^I run bash with:$/) do |text|
|
61
|
+
FileUtils.copy_entry(@cwd, File.join(@dir, 'erc20'))
|
62
|
+
@stdout = `#{text}`
|
63
|
+
@exitstatus = $CHILD_STATUS.exitstatus
|
64
|
+
end
|
65
|
+
|
66
|
+
Given(/^It is Unix$/) do
|
67
|
+
pending if Gem.win_platform?
|
68
|
+
end
|
69
|
+
|
70
|
+
Given(/^It is Windows$/) do
|
71
|
+
pending unless Gem.win_platform?
|
72
|
+
end
|
data/lib/erc20/erc20.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: erc20
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
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-
|
11
|
+
date: 2025-02-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eth
|
@@ -80,12 +80,27 @@ dependencies:
|
|
80
80
|
- - ">"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: slop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '4'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '4'
|
83
97
|
description: 'A simple library for making ERC20 manipulations as easy as they can
|
84
98
|
be for cryptocurrency newbies: checking balance, sending payments, and monitoring
|
85
99
|
addresses for incoming payments. The library expects Etherium node to provide JSON
|
86
100
|
RPC and Websockets API.'
|
87
101
|
email: yegor256@gmail.com
|
88
|
-
executables:
|
102
|
+
executables:
|
103
|
+
- erc20
|
89
104
|
extensions: []
|
90
105
|
extra_rdoc_files:
|
91
106
|
- README.md
|
@@ -117,7 +132,12 @@ files:
|
|
117
132
|
- README.md
|
118
133
|
- REUSE.toml
|
119
134
|
- Rakefile
|
135
|
+
- bin/erc20
|
120
136
|
- erc20.gemspec
|
137
|
+
- features/cli.feature
|
138
|
+
- features/gem_package.feature
|
139
|
+
- features/step_definitions/steps.rb
|
140
|
+
- features/support/env.rb
|
121
141
|
- hardhat/.gitignore
|
122
142
|
- hardhat/Dockerfile
|
123
143
|
- hardhat/contracts/Foo.sol
|