erc20 0.0.2 → 0.0.4

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: bf1f0dbee9d090079bd263a79eeafc0093866fc5503d7a1130b26e7b77ca8630
4
- data.tar.gz: 105f04b7df7e9b8f45a3c34acb739fb6b74238e9f7180b624ceb724f8a4c1570
3
+ metadata.gz: 6b5bccf0ea259136bad39ab36f01240da8a029958b627ed337cd20477a7a13c9
4
+ data.tar.gz: 4c5d605e086d38755d25d8153c0bf6b220460f5b984607fd304706fe0b3d942f
5
5
  SHA512:
6
- metadata.gz: e86283d48937fca5b956c0963b19c6b25b25226d6a60bd737e37d6201cc5dc82879d33ab79ff3ef919728762da601aa9d1bc56aaa85b94532f7edcafd29f04eb
7
- data.tar.gz: f11fd8b7d8b017c4fbdc70b4442aa054344fee9451fd029e7826da8fe12961ac60447522945e83b941ab7ccf28a67299a9077c47b114f8736336d42c6b16088f
6
+ metadata.gz: 0adbab22a3b752f63e1e001eac554ba8bcc8a40a2fea7234b9d674608eb281c912fb2e21931497006509b8cf2ae80e82d9de8dd49b7727f48759796da375d43b
7
+ data.tar.gz: ae3387a6c71c5ba367c8bd5814d2eebced21d6de6087dc214b083659811e2ed60efb5d0d981b7ba57b10030435566645ddd8328ac99ef4f9574b534192385383
data/.rubocop.yml CHANGED
@@ -43,8 +43,10 @@ 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
- Max: 50
49
+ Max: 100
48
50
  Metrics/CyclomaticComplexity:
49
51
  Max: 25
50
52
  Metrics/PerceivedComplexity:
data/Gemfile.lock CHANGED
@@ -6,7 +6,6 @@ PATH
6
6
  eth (~> 0.4)
7
7
  jsonrpc-client (> 0)
8
8
  loog (> 0)
9
- tago (> 0)
10
9
  websocket-client-simple (> 0)
11
10
 
12
11
  GEM
data/README.md CHANGED
@@ -11,17 +11,19 @@
11
11
  [![Hits-of-Code](https://hitsofcode.com/github/yegor256/erc20)](https://hitsofcode.com/view/github/yegor256/erc20)
12
12
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/yegor256/erc20/blob/master/LICENSE.txt)
13
13
 
14
- This small Ruby library makes manipulations with [Etherium] [ERC20] tokens
14
+ This small Ruby [gem](https://rubygems.org/gems/erc20)
15
+ makes manipulations with [Etherium] [ERC20] tokens
15
16
  as simple as they can be, if you have a provider of
16
17
  [JSON-RPC] and [WebSocket] Etherium APIs, for example
17
18
  [Infura], [GetBlock], or [Alchemy]:
18
19
 
19
20
  ```ruby
20
21
  # Create a wallet:
22
+ require 'erc20'
21
23
  w = ERC20::Wallet.new(
22
24
  contract: ERC20::Wallet.USDT, # hex of it
23
- rpc: 'https://mainnet.infura.io/v3/<your-key>',
24
- wss: 'wss://mainnet.infura.io/v3/<your-key>',
25
+ host: 'mainnet.infura.io',
26
+ path: '/v3/<your-key>',
25
27
  log: $stdout
26
28
  )
27
29
 
@@ -34,9 +36,9 @@ txn = w.pay(private_key, to_address, amount)
34
36
  # Stay waiting, and trigger the block when transactions arrive:
35
37
  addresses = ['0x...', '0x...']
36
38
  w.accept(addresses) do |event|
37
- puts event['data'].to_i(16)) # how much
38
- puts "0x#{event['topics'][1][26..]}" # who sent the payment
39
- puts "0x#{event['topics'][2][26..]}" # who was the receiver
39
+ puts event[:amount] # how much
40
+ puts event[:from] # who sent the payment
41
+ puts event[:to] # who was the receiver
40
42
  end
41
43
  ```
42
44
 
data/erc20.gemspec CHANGED
@@ -43,7 +43,6 @@ Gem::Specification.new do |s|
43
43
  s.add_dependency 'eth', '~>0.4'
44
44
  s.add_dependency 'jsonrpc-client', '>0'
45
45
  s.add_dependency 'loog', '>0'
46
- s.add_dependency 'tago', '>0'
47
46
  s.add_dependency 'websocket-client-simple', '>0'
48
47
  s.metadata['rubygems_mfa_required'] = 'true'
49
48
  end
data/lib/erc20/wallet.rb CHANGED
@@ -41,11 +41,28 @@ class ERC20::Wallet
41
41
  # @param [String] contract Hex of the contract in Etherium
42
42
  # @param [String] rpc The URL of Etherium JSON-RPC provider
43
43
  # @param [Integer] chain The ID of the chain (1 for mainnet)
44
+ # @param [String] host The host to connect to
45
+ # @param [Integer] port TCP port to use
46
+ # @param [String] path The path in the connection URL
47
+ # @param [Boolean] ssl Should we use SSL (for https and wss)
44
48
  # @param [Object] log The destination for logs
45
- def initialize(contract: USDT, rpc: nil, wss: nil, chain: 1, log: $stdout)
49
+ def initialize(contract: USDT, rpc: nil, wss: nil, chain: 1, log: $stdout,
50
+ host: nil, port: 443, path: '/', ssl: true)
46
51
  @contract = contract
47
- @rpc = rpc
48
- @wss = wss
52
+ raise 'Use either host or rpc' if rpc && host
53
+ raise 'Use either host or wss' if wss && host
54
+ if rpc
55
+ @rpc = rpc
56
+ else
57
+ raise 'Either rpc or host+port+path are required' unless host && port && path
58
+ @rpc = "http#{ssl ? 's' : ''}://#{host}:#{port}#{path}"
59
+ end
60
+ if wss
61
+ @wss = wss
62
+ else
63
+ raise 'Either wss or host+port+path are required' unless host && port && path
64
+ @wss = "http#{ssl ? 's' : ''}://#{host}:#{port}#{path}"
65
+ end
49
66
  @log = log
50
67
  @chain = chain
51
68
  end
@@ -59,7 +76,9 @@ class ERC20::Wallet
59
76
  padded = "000000000000000000000000#{hex[2..].downcase}"
60
77
  data = "0x#{func}#{padded}"
61
78
  r = jsonrpc.eth_call({ to: @contract, data: data }, 'latest')
62
- r[2..].to_i(16)
79
+ b = r[2..].to_i(16)
80
+ @log.debug("Balance of #{hex} is #{b}")
81
+ b
63
82
  end
64
83
 
65
84
  # Send a single payment from a private address to a public one.
@@ -92,7 +111,10 @@ class ERC20::Wallet
92
111
  }
93
112
  )
94
113
  tx.sign(key)
95
- jsonrpc.eth_sendRawTransaction("0x#{tx.hex}")
114
+ hex = "0x#{tx.hex}"
115
+ jsonrpc.eth_sendRawTransaction(hex)
116
+ @log.debug("Sent #{amount} from #{from} to #{address}: #{hex}")
117
+ hex
96
118
  end
97
119
 
98
120
  # Wait for incoming transactions and let the block know when they
@@ -101,7 +123,8 @@ class ERC20::Wallet
101
123
  #
102
124
  # @param [Array<String>] addresses Addresses to monitor
103
125
  # @param [Array] ready When connected, TRUE will be added to this array
104
- def accept(addresses, connected: [])
126
+ # @param [Boolean] raw TRUE if you need to get JSON events as they arrive from Websockets
127
+ def accept(addresses, connected: [], raw: false)
105
128
  WebSocket::Client::Simple.connect(@wss) do |ws|
106
129
  log = @log
107
130
  contract = @contract
@@ -126,6 +149,7 @@ class ERC20::Wallet
126
149
  }
127
150
  ws.send(msg.to_json)
128
151
  connected.append(1)
152
+ log.debug("Subscribed to #{addresses.count} addresses")
129
153
  end
130
154
  ws.on(:message) do |msg|
131
155
  data =
@@ -136,7 +160,14 @@ class ERC20::Wallet
136
160
  end
137
161
  if data['method'] == 'eth_subscription' && data.dig('params', 'result')
138
162
  event = data['params']['result']
139
- log.debug("New transaction from: #{event['address']}")
163
+ unless raw
164
+ event = {
165
+ amount: event['data'].to_i(16),
166
+ from: "0x#{event['topics'][1][26..].downcase}",
167
+ to: "0x#{event['topics'][2][26..].downcase}"
168
+ }
169
+ end
170
+ log.debug("New event arrived from #{event['address']}")
140
171
  yield event
141
172
  end
142
173
  end
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.2'
30
+ VERSION = '0.0.4'
31
31
  end
@@ -62,6 +62,7 @@ class TestWallet < Minitest::Test
62
62
  def test_fails_with_invalid_infura_key
63
63
  w = ERC20::Wallet.new(
64
64
  rpc: 'https://mainnet.infura.io/v3/invalid-key-here',
65
+ wss: 'https://mainnet.infura.io/v3/another-invalid-key-here',
65
66
  log: Loog::NULL
66
67
  )
67
68
  assert_raises(StandardError) { w.balance(STABLE_ADDRESS) }
@@ -113,11 +114,9 @@ class TestWallet < Minitest::Test
113
114
  wait_for { !event.nil? }
114
115
  daemon.kill
115
116
  daemon.join(30)
116
- assert_equal(sum, event['data'].to_i(16))
117
- from = "0x#{event['topics'][1][26..].downcase}"
118
- assert_equal(jeff, from)
119
- to = "0x#{event['topics'][2][26..].downcase}"
120
- assert_equal(walter, to)
117
+ assert_equal(sum, event[:amount])
118
+ assert_equal(jeff, event[:from])
119
+ assert_equal(walter, event[:to])
121
120
  end
122
121
  end
123
122
 
@@ -128,7 +127,7 @@ class TestWallet < Minitest::Test
128
127
  loop do
129
128
  sleep(0.1)
130
129
  break if yield
131
- raise 'timeout' if Time.now - start > 15
130
+ raise 'timeout' if Time.now - start > 60
132
131
  rescue Errno::ECONNREFUSED
133
132
  retry
134
133
  end
@@ -148,8 +147,8 @@ class TestWallet < Minitest::Test
148
147
  [
149
148
  "https://mainnet.infura.io/v3/#{env('INFURA_KEY')}",
150
149
  "https://go.getblock.io/#{env('GETBLOCK_KEY')}"
151
- ].map do |rpc|
152
- ERC20::Wallet.new(rpc:, log: Loog::NULL)
150
+ ].map do |url|
151
+ ERC20::Wallet.new(rpc: url, wss: url, log: Loog::NULL)
153
152
  end.sample
154
153
  end
155
154
 
@@ -157,8 +156,8 @@ class TestWallet < Minitest::Test
157
156
  [
158
157
  "https://sepolia.infura.io/v3/#{env('INFURA_KEY')}",
159
158
  "https://go.getblock.io/#{env('GETBLOCK_SEPOILA_KEY')}"
160
- ].map do |rpc|
161
- ERC20::Wallet.new(rpc:, log: Loog::NULL)
159
+ ].map do |url|
160
+ ERC20::Wallet.new(rpc: url, wss: url, log: Loog::NULL)
162
161
  end.sample
163
162
  end
164
163
 
@@ -186,8 +185,7 @@ class TestWallet < Minitest::Test
186
185
  ).split("\n").last
187
186
  wallet = ERC20::Wallet.new(
188
187
  contract:, chain: 4242,
189
- rpc: "http://localhost:#{port}",
190
- wss: "ws://localhost:#{port}",
188
+ host: 'localhost', port:, path: '/', ssl: false,
191
189
  log: Loog::NULL
192
190
  )
193
191
  yield wallet
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erc20
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - ">"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: tago
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">"
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">"
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: websocket-client-simple
85
71
  requirement: !ruby/object:Gem::Requirement