erc20 0.0.8 → 0.0.10

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: 2a6045ef455a8f096b144b8a680abd27df0b56c3d66b55893ad7f0f3dc4e4203
4
- data.tar.gz: e5276a87ad3ac48ec1df0928e28bc18295e3033a280fe1172d1d9199b582c54f
3
+ metadata.gz: 34581e0a63fe07f3910a76e45848204045119efd01aaa0d2478d8c2ab7b2cac2
4
+ data.tar.gz: 21086a1c737f697d7ac6bc8c3b4f21845c104f007daca5c9091dfdf46bdb53e4
5
5
  SHA512:
6
- metadata.gz: e964c619368827683031db7eae717c662cc292eb60b0cded4868968e19bdebb1ab091c3ad1edc65e78aa4d0ba2b451587b9f77cf38ac381765776a7b078182f6
7
- data.tar.gz: 83793a79b62811b4f34589a5d60db5cec07f707e04673ef02adcf29e81eaf7d91f3ad7198d2c4bbfc2645032cf8a6c2ac508ec477a3a60edf5874401864c2e20
6
+ metadata.gz: dda126cea1191e735bed9d3ab733c37a42ab0bef1d4566a84fedd0cb4462d9269f974a35256c9367f054e7b2147f657e8d92e267e669e56d24d2691d332a182e
7
+ data.tar.gz: 5b2787b755d7a7d6c1527dd7c0d5b5bf4e824eeeea5b0c9190ad7d2d3899c768ba85b1c1cd93d51c67539e369a0e978bfef296d550996eb2b83e9685b0cdf386
data/.rultor.yml CHANGED
@@ -31,8 +31,8 @@ release:
31
31
  [[ "${tag}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || exit -1
32
32
  DONCE_SUDO=true bundle exec rake
33
33
  rm -rf *.gem
34
- sed -i "s/0\.0\.0/${tag}/g" lib/erc20.rb
35
- git add lib/erc20.rb
34
+ sed -i "s/0\.0\.0/${tag}/g" lib/erc20/erc20.rb
35
+ git add lib/erc20/erc20.rb
36
36
  git commit -m "version set to ${tag}"
37
37
  gem build erc20.gemspec
38
38
  chmod 0600 ../rubygems.yml
data/Gemfile.lock CHANGED
@@ -51,7 +51,7 @@ GEM
51
51
  connection_pool (2.5.0)
52
52
  crass (1.0.6)
53
53
  date (3.4.1)
54
- diff-lcs (1.5.1)
54
+ diff-lcs (1.6.0)
55
55
  docile (1.4.1)
56
56
  donce (0.1.0)
57
57
  backtrace (> 0)
@@ -103,7 +103,7 @@ GEM
103
103
  keccak (1.3.2)
104
104
  konstructor (1.0.2)
105
105
  language_server-protocol (3.17.0.4)
106
- logger (1.6.5)
106
+ logger (1.6.6)
107
107
  loofah (2.24.0)
108
108
  crass (~> 1.0.2)
109
109
  nokogiri (>= 1.12.0)
@@ -147,7 +147,7 @@ GEM
147
147
  loog (> 0)
148
148
  tago (> 0)
149
149
  racc (1.8.1)
150
- rack (3.1.9)
150
+ rack (3.1.10)
151
151
  rack-session (2.1.0)
152
152
  base64 (>= 0.1.0)
153
153
  rack (>= 3.0.0)
data/README.md CHANGED
@@ -14,7 +14,7 @@
14
14
  This small Ruby [gem](https://rubygems.org/gems/erc20)
15
15
  makes manipulations with [Etherium] [ERC20] tokens
16
16
  as simple as they can be, if you have a provider of
17
- [JSON-RPC] and [WebSocket] Etherium APIs, for example
17
+ [JSON-RPC] and [WebSockets] Etherium APIs, for example
18
18
  [Infura], [GetBlock], or [Alchemy]:
19
19
 
20
20
  ```ruby
@@ -92,7 +92,7 @@ If it's clean and you don't see any error messages, submit your pull request.
92
92
  [Etherium]: https://en.wikipedia.org/wiki/Ethereum
93
93
  [ERC20]: https://ethereum.org/en/developers/docs/standards/tokens/erc-20/
94
94
  [JSON-RPC]: https://ethereum.org/en/developers/docs/apis/json-rpc/
95
- [Websocket]: https://ethereum.org/en/developers/tutorials/using-websockets/
95
+ [Websockets]: https://ethereum.org/en/developers/tutorials/using-websockets/
96
96
  [Infura]: https://infura.io/
97
97
  [Alchemy]: https://alchemy.com/
98
98
  [GetBlock]: https://getblock.io/
data/erc20.gemspec CHANGED
@@ -21,7 +21,7 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'English'
24
- require_relative 'lib/erc20'
24
+ require_relative 'lib/erc20/erc20'
25
25
 
26
26
  Gem::Specification.new do |s|
27
27
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2025 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ # This module makes manipulations with Etherium ERC20 tokens
24
+ # as simple as they can be, if you have a provider of
25
+ # JSON-RPC and WebSockets Etherium APIs, for example
26
+ # Infura, GetBlock, or Alchemy.
27
+ #
28
+ # Start like this:
29
+ #
30
+ # require 'erc20'
31
+ # w = ERC20::Wallet.new(
32
+ # host: 'mainnet.infura.io',
33
+ # http_path: '/v3/<your-infura-key>',
34
+ # ws_path: '/ws/v3/<your-infura-key>'
35
+ # )
36
+ # puts w.balance(address)
37
+ #
38
+ # This should print the balance of the ERC20 address.
39
+ #
40
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
41
+ # Copyright:: Copyright (c) 2025 Yegor Bugayenko
42
+ # License:: MIT
43
+ module ERC20
44
+ # Current version of the gem (changed by the +.rultor.yml+ on every release)
45
+ VERSION = '0.0.10'
46
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2025 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require_relative 'erc20'
24
+ require_relative 'wallet'
25
+
26
+ # A fake wallet that behaves like a +ERC20::Wallet+.
27
+ #
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2025 Yegor Bugayenko
30
+ # License:: MIT
31
+ class ERC20::FakeWallet
32
+ # Fakes:
33
+ attr_reader :host, :port, :ssl, :chain, :contract, :ws_path, :http_path
34
+
35
+ # Ctor.
36
+ def initialize
37
+ @host = 'example.com'
38
+ @port = 443
39
+ @ssl = true
40
+ @chain = 1
41
+ @contract = ERC20::Wallet::USDT
42
+ @ws_path = '/'
43
+ @http_path = '/'
44
+ end
45
+
46
+ # Get balance of a public address.
47
+ #
48
+ # @param [String] _hex Public key, in hex, starting from '0x'
49
+ # @return [Integer] Balance, in tokens
50
+ def balance(_hex)
51
+ 42_000_000
52
+ end
53
+
54
+ # Send a single payment from a private address to a public one.
55
+ #
56
+ # @param [String] _priv Private key, in hex
57
+ # @param [String] _address Public key, in hex
58
+ # @param [Integer] _amount The amount of ERC20 tokens to send
59
+ # @return [String] Transaction hash
60
+ def pay(_priv, _address, _amount, *)
61
+ '0x172de9cda30537eae68ab4a96163ebbb8f8a85293b8737dd2e5deb4714b14623'
62
+ end
63
+
64
+ # Wait and accept.
65
+ #
66
+ # @param [Array<String>] addresses Addresses to monitor
67
+ # @param [Array] active List of addresses that we are actually listening to
68
+ # @param [Boolean] raw TRUE if you need to get JSON events as they arrive from Websockets
69
+ # @param [Integer] delay How many seconds to wait between +eth_subscribe+ calls
70
+ def accept(addresses, active = [], raw: false, delay: 1)
71
+ addresses.to_a.each { |a| active.append(a) }
72
+ loop do
73
+ event =
74
+ if raw
75
+ {}
76
+ else
77
+ {
78
+ amount: 424_242,
79
+ from: '0xd5ff1bfcde7a03da61ad229d962c74f1ea2f16a5',
80
+ to: addresses.sample,
81
+ txn: '0x172de9cda30537eae68ab4a96163ebbb8f8a85293b8737dd2e5deb4714b14623'
82
+ }
83
+ end
84
+ yield event
85
+ sleep(delay)
86
+ end
87
+ end
88
+ end
data/lib/erc20/wallet.rb CHANGED
@@ -27,12 +27,49 @@ require 'json'
27
27
  require 'jsonrpc/client'
28
28
  require 'loog'
29
29
  require 'uri'
30
- require_relative '../erc20'
30
+ require_relative 'erc20'
31
31
 
32
32
  # A wallet with ERC20 tokens on Etherium.
33
33
  #
34
34
  # Objects of this class are thread-safe.
35
35
  #
36
+ # In order to check the balance of ERC20 address:
37
+ #
38
+ # require 'erc20'
39
+ # w = ERC20::Wallet.new(
40
+ # contract: ERC20::Wallet.USDT, # hex of it
41
+ # host: 'mainnet.infura.io',
42
+ # http_path: '/v3/<your-infura-key>',
43
+ # ws_path: '/ws/v3/<your-infura-key>',
44
+ # log: $stdout
45
+ # )
46
+ # usdt = w.balance(address)
47
+ #
48
+ # In order to send a payment:
49
+ #
50
+ # hex = w.pay(private_key, to_address, amount)
51
+ #
52
+ # In order to catch incoming payments to a set of addresses:
53
+ #
54
+ # addresses = ['0x...', '0x...']
55
+ # w.accept(addresses) do |event|
56
+ # puts event[:txt] # hash of transaction
57
+ # puts event[:amount] # how much, in tokens (1000000 = $1 USDT)
58
+ # puts event[:from] # who sent the payment
59
+ # puts event[:to] # who was the receiver
60
+ # end
61
+ #
62
+ # To connect to the server via HTTP proxy with basic authentication:
63
+ #
64
+ # w = ERC20::Wallet.new(
65
+ # host: 'go.getblock.io',
66
+ # http_path: '/<your-rpc-getblock-key>',
67
+ # ws_path: '/<your-ws-getblock-key>',
68
+ # proxy: 'http://jeffrey:swordfish@example.com:3128' # here!
69
+ # )
70
+ #
71
+ # More information in our README.
72
+ #
36
73
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
37
74
  # Copyright:: Copyright (c) 2025 Yegor Bugayenko
38
75
  # License:: MIT
@@ -71,7 +108,7 @@ class ERC20::Wallet
71
108
  # Get balance of a public address.
72
109
  #
73
110
  # @param [String] hex Public key, in hex, starting from '0x'
74
- # @return [Integer] Balance, in
111
+ # @return [Integer] Balance, in tokens
75
112
  def balance(hex)
76
113
  func = '70a08231' # balanceOf
77
114
  padded = "000000000000000000000000#{hex[2..].downcase}"
data/lib/erc20.rb CHANGED
@@ -20,12 +20,5 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- # ERC20 module.
24
- #
25
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
26
- # Copyright:: Copyright (c) 2025 Yegor Bugayenko
27
- # License:: MIT
28
- module ERC20
29
- # Current version of the gem (changed by .rultor.yml on every release)
30
- VERSION = '0.0.8'
31
- end
23
+ require_relative 'erc20/erc20'
24
+ require_relative 'erc20/wallet'
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2025 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'backtrace'
24
+ require 'donce'
25
+ require 'eth'
26
+ require 'faraday'
27
+ require 'loog'
28
+ require 'minitest/autorun'
29
+ require 'random-port'
30
+ require 'shellwords'
31
+ require 'threads'
32
+ require 'typhoeus'
33
+ require_relative '../../lib/erc20/fake_wallet'
34
+ require_relative '../test__helper'
35
+
36
+ # Test.
37
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
38
+ # Copyright:: Copyright (c) 2025 Yegor Bugayenko
39
+ # License:: MIT
40
+ class TestFakeWallet < Minitest::Test
41
+ def test_checks_fake_balance
42
+ b = ERC20::FakeWallet.new.balance('0xEB2fE8872A6f1eDb70a2632Effffffffffffffff')
43
+ refute_nil(b)
44
+ end
45
+
46
+ def test_returns_host
47
+ assert_equal('example.com', ERC20::FakeWallet.new.host)
48
+ end
49
+
50
+ def test_pays_fake_money
51
+ priv = '81a9b2114d53731ecc84b261ef6c0387dde34d5907fe7b441240cc21d61bf80a'
52
+ to = '0xfadef8ba4a5d709a2bf55b7a8798c9b438c640c1'
53
+ txn = ERC20::FakeWallet.new.pay(Eth::Key.new(priv:), to, 555)
54
+ assert_equal(66, txn.length)
55
+ assert_match(/^0x[a-f0-9]{64}$/, txn)
56
+ end
57
+
58
+ def test_accepts_payments_on_hardhat
59
+ active = []
60
+ event = nil
61
+ daemon =
62
+ Thread.new do
63
+ ERC20::FakeWallet.new.accept(['0xfadef8ba4a5d709a2bf55b7a8798c9b438c640c1'], active) do |e|
64
+ event = e
65
+ end
66
+ rescue StandardError => e
67
+ loog.error(Backtrace.new(e))
68
+ end
69
+ wait_for { !active.empty? }
70
+ daemon.kill
71
+ daemon.join(30)
72
+ refute_nil(event)
73
+ end
74
+ end
@@ -30,7 +30,6 @@ require 'random-port'
30
30
  require 'shellwords'
31
31
  require 'threads'
32
32
  require 'typhoeus'
33
- require_relative '../../lib/erc20'
34
33
  require_relative '../../lib/erc20/wallet'
35
34
  require_relative '../test__helper'
36
35
 
@@ -261,25 +260,6 @@ class TestWallet < Minitest::Test
261
260
 
262
261
  private
263
262
 
264
- def loog
265
- ENV['RAKE'] ? Loog::ERRORS : Loog::VERBOSE
266
- end
267
-
268
- def wait_for
269
- start = Time.now
270
- loop do
271
- sleep(0.1)
272
- break if yield
273
- raise 'timeout' if Time.now - start > 60
274
- rescue Errno::ECONNREFUSED
275
- retry
276
- end
277
- end
278
-
279
- def wait_for_port(port)
280
- wait_for { Typhoeus::Request.get("http://localhost:#{port}").code == 200 }
281
- end
282
-
283
263
  def env(var)
284
264
  key = ENV.fetch(var, nil)
285
265
  skip("The #{var} environment variable is not set") if key.nil?
data/test/test__helper.rb CHANGED
@@ -39,3 +39,28 @@ if ENV['RAKE']
39
39
  require 'minitest/retry'
40
40
  Minitest::Retry.use!(methods_to_skip: [])
41
41
  end
42
+
43
+ # Test.
44
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
45
+ # Copyright:: Copyright (c) 2025 Yegor Bugayenko
46
+ # License:: MIT
47
+ class Minitest::Test
48
+ def loog
49
+ ENV['RAKE'] ? Loog::ERRORS : Loog::VERBOSE
50
+ end
51
+
52
+ def wait_for
53
+ start = Time.now
54
+ loop do
55
+ sleep(0.1)
56
+ break if yield
57
+ raise 'timeout' if Time.now - start > 60
58
+ rescue Errno::ECONNREFUSED
59
+ retry
60
+ end
61
+ end
62
+
63
+ def wait_for_port(port)
64
+ wait_for { Typhoeus::Request.get("http://localhost:#{port}").code == 200 }
65
+ end
66
+ end
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.8
4
+ version: 0.0.10
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-13 00:00:00.000000000 Z
11
+ date: 2025-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eth
@@ -122,8 +122,11 @@ files:
122
122
  - hardhat/ignition/modules/Foo.ts
123
123
  - hardhat/package.json
124
124
  - lib/erc20.rb
125
+ - lib/erc20/erc20.rb
126
+ - lib/erc20/fake_wallet.rb
125
127
  - lib/erc20/wallet.rb
126
128
  - renovate.json
129
+ - test/erc20/test_fake_wallet.rb
127
130
  - test/erc20/test_wallet.rb
128
131
  - test/test__helper.rb
129
132
  homepage: http://github.com/yegor256/erc20.rb