erc20 0.0.18 → 0.0.19

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: 37aa39344c429cfd2153f004bd2a92730cd3a22c4f11c04e31573d36a98b2045
4
- data.tar.gz: c64d6baecf8256cce26bad81f16608b01098b1c581a1370dedb05b9761a8a6e2
3
+ metadata.gz: a15afef1a8d918f6594d8ec52f92899c50559f38b8c5ca5fe1ce70cf5123c7e5
4
+ data.tar.gz: 46ce6edcf81eb9a07b16e3b02cd2ca46f9238a07ef3d54566df67ea4260accc6
5
5
  SHA512:
6
- metadata.gz: 030bd6e0734bef65820b1c0a63237eed014bc1e1291e7a98f2e8ffe17bffab6aaa3d6cc9685f0901002512376c6ac2bece5d9c564249259700df82ba2bb609c0
7
- data.tar.gz: 5836008fa63ea04bc68f7e8cc670f18b17ec887be606fedf1315e1d6e94d6be2b21859693c173d7ecd56e173fcd13f4598e08099fca941fb1bedd6367dc16e80
6
+ metadata.gz: 9c2aaca43b303101022c8189159b08bc9193ed210675e8ed343e32849883a37ac78c6b7ad7fe0efd63eb2a91f3deda2c73280091e37d25e8f8ca8eada40f74e4
7
+ data.tar.gz: 04d81a60b8ab53fd4de2559f52e76e3dbf63e8266ffc739a7b1ac046250a6420554e5beb40219efa9e4617e750827d860f64cf3a3071de76f28310143d0ff885
data/.rubocop.yml CHANGED
@@ -28,6 +28,7 @@ AllCops:
28
28
  SuggestExtensions: false
29
29
  NewCops: enable
30
30
  plugins:
31
+ - rubocop-rspec
31
32
  - rubocop-performance
32
33
  - rubocop-rake
33
34
  - rubocop-minitest
@@ -63,4 +64,3 @@ Security/MarshalLoad:
63
64
  Enabled: false
64
65
  Layout/MultilineAssignmentLayout:
65
66
  Enabled: true
66
- require: []
data/Gemfile.lock CHANGED
@@ -223,11 +223,12 @@ GEM
223
223
  lint_roller (~> 1.1)
224
224
  rubocop (>= 1.72.1, < 2.0)
225
225
  rubocop-ast (>= 1.38.0, < 2.0)
226
- rubocop-rake (0.7.0)
226
+ rubocop-rake (0.7.1)
227
227
  lint_roller (~> 1.1)
228
228
  rubocop (>= 1.72.1)
229
- rubocop-rspec (3.4.0)
230
- rubocop (~> 1.61)
229
+ rubocop-rspec (3.5.0)
230
+ lint_roller (~> 1.1)
231
+ rubocop (~> 1.72, >= 1.72.1)
231
232
  ruby-progressbar (1.13.0)
232
233
  rubyzip (2.4.1)
233
234
  scrypt (3.0.8)
data/README.md CHANGED
@@ -83,6 +83,19 @@ You can use [squid-proxy] [Docker] image to set up your own [HTTP proxy] server.
83
83
  Of course, this library works with [Polygon], [Optimism],
84
84
  and other forks of [Etherium].
85
85
 
86
+ ## How to use in tests
87
+
88
+ You can use `ERC20::FakeWallet` class that behaves exactly like
89
+ `ERC20::Wallet`, but doesn't make any network connections to the provider.
90
+ Also, it remembers all requests that were sent to it:
91
+
92
+ ```ruby
93
+ require 'erc20'
94
+ w = ERC20::FakeWallet.new
95
+ w.pay(priv, address, 42_000)
96
+ assert w.history.include?({ method: :pay, params: [priv, address, 42_000] })
97
+ ```
98
+
86
99
  ## How to contribute
87
100
 
88
101
  Read
data/lib/erc20/erc20.rb CHANGED
@@ -42,5 +42,5 @@
42
42
  # License:: MIT
43
43
  module ERC20
44
44
  # Current version of the gem (changed by the +.rultor.yml+ on every release)
45
- VERSION = '0.0.18'
45
+ VERSION = '0.0.19'
46
46
  end
@@ -32,6 +32,9 @@ class ERC20::FakeWallet
32
32
  # Fakes:
33
33
  attr_reader :host, :port, :ssl, :chain, :contract, :ws_path, :http_path
34
34
 
35
+ # Full history of all method calls:
36
+ attr_reader :history
37
+
35
38
  # Ctor.
36
39
  def initialize
37
40
  @host = 'example.com'
@@ -41,40 +44,49 @@ class ERC20::FakeWallet
41
44
  @contract = ERC20::Wallet::USDT
42
45
  @ws_path = '/'
43
46
  @http_path = '/'
47
+ @history = []
44
48
  end
45
49
 
46
50
  # Get ERC20 balance of a public address.
47
51
  #
48
- # @param [String] _hex Public key, in hex, starting from '0x'
52
+ # @param [String] address Public key, in hex, starting from '0x'
49
53
  # @return [Integer] Balance, in tokens
50
- def balance(_hex)
51
- 42_000_000
54
+ def balance(address)
55
+ b = 42_000_000
56
+ @history << { method: :balance, address:, result: b }
57
+ b
52
58
  end
53
59
 
54
60
  # Get ETH balance of a public address.
55
61
  #
56
- # @param [String] _hex Public key, in hex, starting from '0x'
62
+ # @param [String] address Public key, in hex, starting from '0x'
57
63
  # @return [Integer] Balance, in tokens
58
- def eth_balance(_hex)
59
- 42_000_000
64
+ def eth_balance(address)
65
+ b = 77_000_000_000_000_000
66
+ @history << { method: :eth_balance, address:, result: b }
67
+ b
60
68
  end
61
69
 
62
- # How much ETH gas is required in order to send this ETH transaction.
70
+ # How much ETH gas is required in order to send this ERC20 transaction.
63
71
  #
64
- # @param [String] _from The departing address, in hex
65
- # @param [String] _to Arriving address, in hex
72
+ # @param [String] from The departing address, in hex
73
+ # @param [String] to Arriving address, in hex
66
74
  # @return [Integer] How many ETH required
67
- def eth_gas_required(_from, _to)
68
- 55_000
75
+ def gas_required(from, to = from)
76
+ g = 66_000
77
+ @history << { method: :gas_required, from:, to:, result: g }
78
+ g
69
79
  end
70
80
 
71
- # How much ETH gas is required in order to send this ERC20 transaction.
81
+ # How much ETH gas is required in order to send this ETH transaction.
72
82
  #
73
- # @param [String] _from The departing address, in hex
74
- # @param [String] _to Arriving address, in hex
83
+ # @param [String] from The departing address, in hex
84
+ # @param [String] to Arriving address, in hex (may be skipped)
75
85
  # @return [Integer] How many ETH required
76
- def gas_required(_from, _to)
77
- 66_000
86
+ def eth_gas_required(from, to = from)
87
+ g = 55_000
88
+ @history << { method: :eth_gas_required, from:, to:, result: g }
89
+ g
78
90
  end
79
91
 
80
92
  # Send a single ERC20 payment from a private address to a public one.
@@ -83,18 +95,22 @@ class ERC20::FakeWallet
83
95
  # @param [String] _address Public key, in hex
84
96
  # @param [Integer] _amount The amount of ERC20 tokens to send
85
97
  # @return [String] Transaction hash
86
- def pay(_priv, _address, _amount, *)
87
- '0x172de9cda30537eae68ab4a96163ebbb8f8a85293b8737dd2e5deb4714b14623'
98
+ def pay(priv, address, amount, gas_limit: nil, gas_price: nil)
99
+ hex = '0x172de9cda30537eae68ab4a96163ebbb8f8a85293b8737dd2e5deb4714b14623'
100
+ @history << { method: :pay, priv:, address:, amount:, gas_limit:, gas_price:, result: hex }
101
+ hex
88
102
  end
89
103
 
90
104
  # Send a single ETH payment from a private address to a public one.
91
105
  #
92
- # @param [String] _priv Private key, in hex
93
- # @param [String] _address Public key, in hex
94
- # @param [Integer] _amount The amount of ETHs to send
106
+ # @param [String] priv Private key, in hex
107
+ # @param [String] address Public key, in hex
108
+ # @param [Integer] amount The amount of ETHs to send
95
109
  # @return [String] Transaction hash
96
- def eth_pay(_priv, _address, _amount, *)
97
- '0x172de9cda30537eae68ab4a96163ebbb8f8a85293b8737dd2e5deb4714b14623'
110
+ def eth_pay(priv, address, amount, gas_limit: nil, gas_price: nil)
111
+ hex = '0x172de9cda30537eae68ab4a96163ebbb8f8a85293b8737dd2e5deb4714b14623'
112
+ @history << { method: :eth_pay, priv:, address:, amount:, gas_limit:, gas_price:, result: hex }
113
+ hex
98
114
  end
99
115
 
100
116
  # Wait and accept.
@@ -104,6 +120,7 @@ class ERC20::FakeWallet
104
120
  # @param [Boolean] raw TRUE if you need to get JSON events as they arrive from Websockets
105
121
  # @param [Integer] delay How many seconds to wait between +eth_subscribe+ calls
106
122
  def accept(addresses, active = [], raw: false, delay: 1)
123
+ @history << { method: :accept, addresses:, active:, raw:, delay: }
107
124
  addresses.to_a.each { |a| active.append(a) }
108
125
  loop do
109
126
  sleep(delay)
data/lib/erc20/wallet.rb CHANGED
@@ -165,6 +165,12 @@ class ERC20::Wallet
165
165
  # @param [String] to Arriving address, in hex (it's OK to skip it)
166
166
  # @return [Integer] How many ETH required
167
167
  def gas_required(from, to = from)
168
+ raise 'Address can\'t be nil' unless from
169
+ raise 'Address must be a String' unless from.is_a?(String)
170
+ raise 'Invalid format of the address' unless /^0x[0-9a-fA-F]{40}$/.match?(from)
171
+ raise 'Address can\'t be nil' unless to
172
+ raise 'Address must be a String' unless to.is_a?(String)
173
+ raise 'Invalid format of the address' unless /^0x[0-9a-fA-F]{40}$/.match?(to)
168
174
  gas_estimate(from, to, to_pay_data(from, 100_000))
169
175
  end
170
176
 
@@ -174,6 +180,12 @@ class ERC20::Wallet
174
180
  # @param [String] to Arriving address, in hex (it's OK to skip it)
175
181
  # @return [Integer] How many ETH required
176
182
  def eth_gas_required(from, to = from)
183
+ raise 'Address can\'t be nil' unless from
184
+ raise 'Address must be a String' unless from.is_a?(String)
185
+ raise 'Invalid format of the address' unless /^0x[0-9a-fA-F]{40}$/.match?(from)
186
+ raise 'Address can\'t be nil' unless to
187
+ raise 'Address must be a String' unless to.is_a?(String)
188
+ raise 'Invalid format of the address' unless /^0x[0-9a-fA-F]{40}$/.match?(to)
177
189
  gas_estimate(from, to)
178
190
  end
179
191
 
@@ -39,29 +39,29 @@ require_relative '../test__helper'
39
39
  # License:: MIT
40
40
  class TestFakeWallet < Minitest::Test
41
41
  def test_checks_gas_required
42
- b = ERC20::FakeWallet.new.gas_required(
43
- '0xEB2fE8872A6f1eDb70a2632Effffffffffffffff',
44
- '0xEB2fE8872A6f1eDb70a2632Effffffffffffffff'
45
- )
42
+ b = ERC20::FakeWallet.new.gas_required('0xEB2fE8872A6f1eDb70a2632Effffffffffffffff')
46
43
  refute_nil(b)
47
44
  end
48
45
 
49
46
  def test_checks_eth_gas_required
50
- b = ERC20::FakeWallet.new.eth_gas_required(
51
- '0xEB2fE8872A6f1eDb70a2632Effffffffffffffff',
52
- '0xEB2fE8872A6f1eDb70a2632Effffffffffffffff'
53
- )
47
+ b = ERC20::FakeWallet.new.eth_gas_required('0xEB2fE8872A6f1eDb70a2632Effffffffffffffff')
54
48
  refute_nil(b)
55
49
  end
56
50
 
57
51
  def test_checks_fake_balance
58
- b = ERC20::FakeWallet.new.balance('0xEB2fE8872A6f1eDb70a2632Effffffffffffffff')
52
+ w = ERC20::FakeWallet.new
53
+ a = '0xEB2fE8872A6f1eDb70a2632Effffffffffffffff'
54
+ b = w.balance(a)
59
55
  refute_nil(b)
56
+ assert_includes(w.history, { method: :balance, result: b, address: a })
60
57
  end
61
58
 
62
59
  def test_checks_fake_eth_balance
63
- b = ERC20::FakeWallet.new.eth_balance('0xEB2fE8872A6f1eDb70a2632Effffffffffffffff')
60
+ a = '0xEB2fE8872A6f1eDb70a2632Effffffffffffffff'
61
+ w = ERC20::FakeWallet.new
62
+ b = w.eth_balance(a)
64
63
  refute_nil(b)
64
+ assert_includes(w.history, { method: :eth_balance, result: b, address: a })
65
65
  end
66
66
 
67
67
  def test_returns_host
@@ -70,10 +70,13 @@ class TestFakeWallet < Minitest::Test
70
70
 
71
71
  def test_pays_fake_money
72
72
  priv = '81a9b2114d53731ecc84b261ef6c0387dde34d5907fe7b441240cc21d61bf80a'
73
- to = '0xfadef8ba4a5d709a2bf55b7a8798c9b438c640c1'
74
- txn = ERC20::FakeWallet.new.pay(Eth::Key.new(priv:), to, 555)
73
+ address = '0xfadef8ba4a5d709a2bf55b7a8798c9b438c640c1'
74
+ w = ERC20::FakeWallet.new
75
+ amount = 555_000
76
+ txn = w.pay(priv, address, amount)
75
77
  assert_equal(66, txn.length)
76
78
  assert_match(/^0x[a-f0-9]{64}$/, txn)
79
+ assert_includes(w.history, { method: :pay, result: txn, priv:, address:, amount:, gas_limit: nil, gas_price: nil })
77
80
  end
78
81
 
79
82
  def test_pays_fake_eths
@@ -71,6 +71,7 @@ class TestWallet < Minitest::Test
71
71
  b = mainnet.gas_required(STABLE, Eth::Key.new(priv: JEFF).address.to_s)
72
72
  refute_nil(b)
73
73
  assert_predicate(b, :positive?)
74
+ assert_operator(b, :>, 1000)
74
75
  end
75
76
 
76
77
  def test_checks_same_address_gas_required_on_mainnet
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.18
4
+ version: 0.0.19
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-16 00:00:00.000000000 Z
11
+ date: 2025-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eth