pickynode 0.1.4 → 0.2.0

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
- SHA1:
3
- metadata.gz: 702cd10448727e96f341a26c08c971bb0f17bd97
4
- data.tar.gz: 489e7d774e5c27e96595f26e262b24c7c13d68b5
2
+ SHA256:
3
+ metadata.gz: e5fccd137dcf0d78b38edab501a8c3c02b5d1c1dc80ffafcf65cdc18d503906b
4
+ data.tar.gz: c0c8a24d017f7e23404a91dd75c0ef7fcc9daf7317a49429a272a0e093a75f5f
5
5
  SHA512:
6
- metadata.gz: fc42867734de71d7f6febfe971511df2eff482d85e75d638b76bd17059d25e65ef01d5e10762777943def956abe2c4bca6c04e279594804efc8a12d5d7ec5d23
7
- data.tar.gz: 56f4542daf463e1404314e251e298b255ca22f82ab54f844f7e5b4b520a2df75c771cd4f931fdc82c6143f577aefecf0f045dadd39597b1f6fef71254e11f914
6
+ metadata.gz: b5f709d9f1ae5802c2ae07b9c7445882add45955af0afe9bee0b00e89b51c8c33a9283cbf5b95f4c0cc2c7ae58015d6114c5b8e53403c0965de7dd6b3218a08b
7
+ data.tar.gz: fa2e7689fea07663d5eda913742fdd0278c4b030f6c9b59fea7d3677e4bbb29bd0d67ac2e8b98ba36590521a53fe2be901fde83a1b3bb1cd0628e91e301845bf
data/.gitignore CHANGED
@@ -48,3 +48,6 @@ build-iPhoneSimulator/
48
48
 
49
49
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
50
  .rvmrc
51
+
52
+ # Don't check in the Gemfile.lock
53
+ Gemfile.lock
data/.rubocop.yml CHANGED
@@ -1,8 +1,19 @@
1
- ClassLength:
1
+ AllCops:
2
+ TargetRubyVersion: 2.5
3
+ NewCops: disable
4
+ Metrics/ClassLength:
2
5
  Enabled: false
3
6
  Metrics/BlockLength:
4
7
  ExcludedMethods: ['describe', 'context']
5
- Style/IndentHeredoc:
6
- Enabled: false
7
8
  Style/NumericPredicate:
8
9
  Enabled: false
10
+ Lint/RaiseException:
11
+ Enabled: true
12
+ Lint/StructNewOverride:
13
+ Enabled: true
14
+ Style/HashEachMethods:
15
+ Enabled: true
16
+ Style/HashTransformKeys:
17
+ Enabled: true
18
+ Style/HashTransformValues:
19
+ Enabled: true
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.4
1
+ 2.5.3
data/.travis.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "2.2.7"
4
- - "2.3.4"
3
+ - "2.5.0"
4
+ - "3.3.5"
data/Gemfile CHANGED
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  source 'https://rubygems.org'
4
- ruby '>= 2.0'
4
+ ruby '>= 2.5.0'
5
5
 
6
6
  gem 'awesome_print', '~> 1.7'
7
+ gem 'base64', '~> 0.2'
8
+ gem 'optimist', '~> 3.0'
9
+ gem 'ostruct', '~> 0.6'
7
10
  gem 'rake', '~> 12.0'
8
11
  gem 'rspec', '~> 3.6'
9
12
  gem 'rubocop', '~> 0.48'
10
13
  gem 'simplecov', '~> 0.14', require: false, group: :test
11
- gem 'trollop', '~> 2.1'
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017 Josh Ellithorpe
3
+ Copyright (c) 2017-2024 Josh Ellithorpe
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Gem Version](https://badge.fury.io/rb/pickynode.svg)](https://badge.fury.io/rb/pickynode) [![Build Status](https://travis-ci.org/zquestz/pickynode.svg)](https://travis-ci.org/zquestz/pickynode) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
1
+ [![Gem Version](https://badge.fury.io/rb/pickynode.svg)](https://badge.fury.io/rb/pickynode) [![Build Status](https://app.travis-ci.com/zquestz/pickynode.svg?branch=master&status=passed)](https://app.travis-ci.com/github/zquestz/pickynode) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
2
2
  # pickynode
3
3
 
4
4
  Some people are picky about the bitcoin nodes they connect to.
@@ -45,7 +45,7 @@ pickynode --disconnect=USER_AGENT_FILTER
45
45
  ### Help:
46
46
 
47
47
  ```
48
- pickynode v0.1.4
48
+ pickynode v0.2.0
49
49
  Options:
50
50
  -a, --add=<s> Add node type
51
51
  -c, --connect=<s> Connect to node type
@@ -55,8 +55,9 @@ Options:
55
55
  -o, --output Output commands
56
56
  -s, --disconnect=<s> Disconnect from node type
57
57
  -l, --limit=<i> Limit number of nodes to add/connect
58
+ -t, --ticker=<s> Currency ticker symbol (BCH/BTC) (default: BCH)
58
59
  -v, --version Print version and exit
59
60
  -h, --help Show this message
60
61
  ```
61
62
 
62
- The --add and --connect commands pull data from Bitnodes.
63
+ The --add and --connect commands pull data from the Blockchair API.
data/Rakefile CHANGED
File without changes
data/bin/pickynode CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  require 'pickynode'
5
5
 
6
- opts = Trollop.options do
6
+ opts = Optimist.options do
7
7
  version "pickynode v#{Pickynode::VERSION}"
8
8
  opt :add, 'Add node type', type: :string
9
9
  opt :connect, 'Connect to node type', type: :string
@@ -13,7 +13,9 @@ opts = Trollop.options do
13
13
  opt :output, 'Output commands'
14
14
  opt :disconnect, 'Disconnect from node type', type: :string
15
15
  opt :limit, 'Limit number of nodes to add/connect', type: :integer
16
+ opt :ticker, 'Currency ticker symbol (BCH/BTC)', type: :string, default: 'BCH'
16
17
  end
17
18
 
18
- Trollop.die :limit, 'must be positive' if opts[:limit] && opts[:limit] <= 0
19
+ Optimist.die :limit, 'must be positive' if opts[:limit] && opts[:limit] <= 0
20
+ Optimist.die :ticker, 'must be BCH or BTC' unless %w[BCH BTC].include?(opts[:ticker])
19
21
  Pickynode.new(opts).run
data/lib/pickynode.rb CHANGED
@@ -3,13 +3,13 @@
3
3
  require 'awesome_print'
4
4
  require 'json'
5
5
  require 'net/http'
6
- require 'trollop'
6
+ require 'optimist'
7
7
  require 'uri'
8
8
 
9
9
  # Allows you to easily add/ban/connect/disconnect nodes
10
10
  # based on User Agent.
11
11
  class Pickynode
12
- VERSION = '0.1.4'
12
+ VERSION = '0.2.0'
13
13
 
14
14
  def initialize(opts = {})
15
15
  @opts = opts
@@ -20,22 +20,24 @@ class Pickynode
20
20
 
21
21
  validate_limit(limit)
22
22
 
23
- count = 0
24
- bitnode_addr_types.select { |_, v| v.include?(filter) }.each do |k, _|
25
- run_cmd(%(bitcoin-cli addnode "#{k}" "add"))
26
- count += 1
27
- break if limit == count
28
- end
23
+ blockchair_addr_types
24
+ .select { |_, v| v.include?(filter) }
25
+ .each_with_index do |(k, _), i|
26
+ break if limit == i
27
+
28
+ run_cmd(%(bitcoin-cli addnode "#{k}" "add"))
29
+ end
29
30
  end
30
31
 
31
32
  def ban(filter)
32
33
  return unless filter
33
- addr_types.each do |k, v|
34
- if v.include?(filter)
34
+
35
+ addr_types
36
+ .select { |_, v| v.include?(filter) }
37
+ .each do |k, _|
35
38
  u = URI.parse("https://#{k}")
36
39
  run_cmd(%(bitcoin-cli setban "#{u.host}" "add"))
37
40
  end
38
- end
39
41
  end
40
42
 
41
43
  def connect(filter, limit = nil)
@@ -43,19 +45,23 @@ class Pickynode
43
45
 
44
46
  validate_limit(limit)
45
47
 
46
- count = 0
47
- bitnode_addr_types.select { |_, v| v.include?(filter) }.each do |k, _|
48
- run_cmd(%(bitcoin-cli addnode "#{k}" "onetry"))
49
- count += 1
50
- break if limit == count
51
- end
48
+ blockchair_addr_types
49
+ .select { |_, v| v.include?(filter) }
50
+ .each_with_index do |(k, _), i|
51
+ break if limit == i
52
+
53
+ run_cmd(%(bitcoin-cli addnode "#{k}" "onetry"))
54
+ end
52
55
  end
53
56
 
54
57
  def disconnect(filter)
55
58
  return unless filter
56
- addr_types.each do |k, v|
57
- run_cmd(%(bitcoin-cli disconnectnode "#{k}")) if v.include?(filter)
58
- end
59
+
60
+ addr_types
61
+ .select { |_, v| v.include?(filter) }
62
+ .each do |k, _|
63
+ run_cmd(%(bitcoin-cli disconnectnode "#{k}"))
64
+ end
59
65
  end
60
66
 
61
67
  def display
@@ -78,7 +84,7 @@ class Pickynode
78
84
 
79
85
  def clear_cache
80
86
  @addr_types = nil
81
- @bitnode_addr_types = nil
87
+ @blockchair_addr_types = nil
82
88
  end
83
89
 
84
90
  private
@@ -95,6 +101,7 @@ class Pickynode
95
101
 
96
102
  def addr_types
97
103
  return @addr_types if @addr_types
104
+
98
105
  nodes = getpeerinfo
99
106
  parsed_nodes = JSON.parse(nodes)
100
107
  @addr_types = parsed_nodes.map do |n|
@@ -104,22 +111,42 @@ class Pickynode
104
111
  {}
105
112
  end
106
113
 
107
- def bitnode_addr_types
108
- return @bitnode_addr_types if @bitnode_addr_types
109
- parsed_nodelist = JSON.parse(bitnodes_snapshot)
110
- @bitnode_addr_types = parsed_nodelist['nodes'].map do |k, v|
111
- [k, v[1]]
112
- end.to_h
114
+ def blockchair_addr_types
115
+ return @blockchair_addr_types if @blockchair_addr_types
116
+
117
+ parsed_nodelist = JSON.parse(blockchair_snapshot)
118
+ @blockchair_addr_types = parsed_nodelist['data']['nodes'].transform_values do |v|
119
+ v['version']
120
+ end
113
121
  rescue JSON::ParserError
114
122
  {}
115
123
  end
116
124
 
117
- def bitnodes_snapshot
118
- Net::HTTP.get(URI.parse('https://bitnodes.21.co/api/v1/snapshots/latest/'))
125
+ def blockchair_snapshot
126
+ chain = case @opts[:ticker]
127
+ when 'BCH'
128
+ 'bitcoin-cash'
129
+ when 'BTC'
130
+ 'bitcoin'
131
+ end
132
+
133
+ Net::HTTP.get(URI.parse("https://api.blockchair.com/#{chain}/nodes"))
119
134
  end
120
135
 
121
136
  def getinfo
122
- JSON.parse(`bitcoin-cli getinfo`)
137
+ getblockchaininfo.merge(getnetworkinfo)
138
+ rescue JSON::ParserError
139
+ {}
140
+ end
141
+
142
+ def getblockchaininfo
143
+ JSON.parse(`bitcoin-cli getblockchaininfo`)
144
+ rescue JSON::ParserError
145
+ {}
146
+ end
147
+
148
+ def getnetworkinfo
149
+ JSON.parse(`bitcoin-cli getnetworkinfo`)
123
150
  rescue JSON::ParserError
124
151
  {}
125
152
  end
data/pickynode.gemspec CHANGED
@@ -15,13 +15,15 @@ bitcoin nodes they connect to."
15
15
  s.executables << 'pickynode'
16
16
  s.files = `git ls-files`.split("\n")
17
17
  s.require_paths = ['lib']
18
- s.required_ruby_version = '>= 2.0'
18
+ s.required_ruby_version = '>= 2.5'
19
19
 
20
20
  s.add_dependency 'awesome_print', '~> 1.7'
21
- s.add_dependency 'trollop', '~> 2.1'
21
+ s.add_dependency 'base64', '~> 0.2'
22
+ s.add_dependency 'optimist', '~> 3.0'
23
+ s.add_dependency 'ostruct', '~> 0.6'
22
24
 
23
- s.add_development_dependency 'rspec', '~> 3.6'
24
25
  s.add_development_dependency 'rake', '~> 12.0'
26
+ s.add_development_dependency 'rspec', '~> 3.6'
25
27
  s.add_development_dependency 'rubocop', '~> 0.48'
26
28
  s.add_development_dependency 'simplecov', '~> 0.14'
27
29
  end
data/spec/mocks.rb CHANGED
@@ -1,84 +1,93 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- BITNODES_SNAPSHOT = <<-HEREDOC
4
- {
5
- "timestamp": 1495414383,
6
- "total_nodes": 7055,
7
- "latest_height": 467520,
8
- "nodes": {
9
- "88.99.199.87:8333": [80002, "/BitcoinUnlimited:1.0.2(EB16; AD12)/", 1494608364, 5, 467520, "static.87.199.99.88.clients.your-server.de", null, "DE", 51.2993, 9.491, "Europe/Berlin", "AS24940", "Hetzner Online GmbH"],
10
- "[2a01:e34:ee3a:5730:21f:5bff:fec5:e356]:8333": [70015, "/Satoshi:0.14.0/", 1495378733, 13, 467520, "2a01:e34:ee3a:5730:21f:5bff:fec5:e356", null, "FR", 46.0, 2.0, "Europe/Paris", "AS12322", "Free SAS"]
3
+ BLOCKCHAIR_SNAPSHOT = <<~HEREDOC
4
+ {
5
+ "data": {
6
+ "nodes": {
7
+ "88.99.199.87:8333": {
8
+ "version": "\/BitcoinUnlimited:1.0.2(EB16; AD12)\/",
9
+ "country": "US",
10
+ "height": 555417,
11
+ "flags": 37
12
+ },
13
+ "[2a01:e34:ee3a:5730:21f:5bff:fec5:e356]:8333": {
14
+ "version": "\/Satoshi:0.14.0\/",
15
+ "country": "US",
16
+ "height": 555416,
17
+ "flags": 37
18
+ }
19
+ }
20
+ }
11
21
  }
12
- }
13
- HEREDOC
14
-
15
- NODE_INFO = <<-HEREDOC
16
- {
17
- "version": 1020500,
18
- "protocolversion": 70012,
19
- "blocks": 467548,
20
- "timeoffset": 0,
21
- "connections": 154,
22
- "proxy": "",
23
- "difficulty": 559970892890.8381,
24
- "testnet": false,
25
- "paytxfee": 0.00000000,
26
- "relayfee": 0.00001000,
27
- "errors": ""
28
- }
29
22
  HEREDOC
30
23
 
31
- PEER_INFO = <<-HEREDOC
32
- [
24
+ NODE_INFO = <<~HEREDOC
33
25
  {
34
- "id": 2,
35
- "addr": "131.114.88.218:33422",
36
- "addrlocal": "67.188.11.253:8333",
37
- "services": "0000000000000000",
38
- "relaytxes": true,
39
- "lastsend": 1495412829,
40
- "lastrecv": 1495412825,
41
- "bytessent": 5200917,
42
- "bytesrecv": 2044140,
43
- "conntime": 1495393261,
44
- "timeoffset": -24,
45
- "pingtime": 0.369602,
46
- "minping": 0.210565,
47
- "version": 70002,
48
- "subver": "/FirstClient/",
49
- "inbound": true,
50
- "startingheight": 435862,
51
- "banscore": 0,
52
- "synced_headers": 467515,
53
- "synced_blocks": -1,
54
- "inflight": [
55
- ],
56
- "whitelisted": false
57
- },
58
- {
59
- "id": 3,
60
- "addr": "[2a01:e34:ee3a:5730:21f:5bff:fec5:e356]:8333",
61
- "addrlocal": "[2a01:e34:ee3a:5730:21f:5bff:fec5:e356]:8333",
62
- "services": "0000000000000005",
63
- "relaytxes": true,
64
- "lastsend": 1495412829,
65
- "lastrecv": 1495412830,
66
- "bytessent": 10235040,
67
- "bytesrecv": 2729345,
68
- "conntime": 1495393262,
69
- "timeoffset": -11,
70
- "pingtime": 0.275245,
71
- "minping": 0.07081899999999999,
72
- "version": 80002,
73
- "subver": "/SecondClient/",
74
- "inbound": false,
75
- "startingheight": 467483,
76
- "banscore": 0,
77
- "synced_headers": 467515,
78
- "synced_blocks": 467515,
79
- "inflight": [
80
- ],
81
- "whitelisted": false
26
+ "version": 1020500,
27
+ "protocolversion": 70012,
28
+ "blocks": 467548,
29
+ "timeoffset": 0,
30
+ "connections": 154,
31
+ "proxy": "",
32
+ "difficulty": 559970892890.8381,
33
+ "testnet": false,
34
+ "paytxfee": 0.00000000,
35
+ "relayfee": 0.00001000,
36
+ "errors": ""
82
37
  }
83
- ]
38
+ HEREDOC
39
+
40
+ PEER_INFO = <<~HEREDOC
41
+ [
42
+ {
43
+ "id": 2,
44
+ "addr": "131.114.88.218:33422",
45
+ "addrlocal": "67.188.11.253:8333",
46
+ "services": "0000000000000000",
47
+ "relaytxes": true,
48
+ "lastsend": 1495412829,
49
+ "lastrecv": 1495412825,
50
+ "bytessent": 5200917,
51
+ "bytesrecv": 2044140,
52
+ "conntime": 1495393261,
53
+ "timeoffset": -24,
54
+ "pingtime": 0.369602,
55
+ "minping": 0.210565,
56
+ "version": 70002,
57
+ "subver": "/FirstClient/",
58
+ "inbound": true,
59
+ "startingheight": 435862,
60
+ "banscore": 0,
61
+ "synced_headers": 467515,
62
+ "synced_blocks": -1,
63
+ "inflight": [
64
+ ],
65
+ "whitelisted": false
66
+ },
67
+ {
68
+ "id": 3,
69
+ "addr": "[2a01:e34:ee3a:5730:21f:5bff:fec5:e356]:8333",
70
+ "addrlocal": "[2a01:e34:ee3a:5730:21f:5bff:fec5:e356]:8333",
71
+ "services": "0000000000000005",
72
+ "relaytxes": true,
73
+ "lastsend": 1495412829,
74
+ "lastrecv": 1495412830,
75
+ "bytessent": 10235040,
76
+ "bytesrecv": 2729345,
77
+ "conntime": 1495393262,
78
+ "timeoffset": -11,
79
+ "pingtime": 0.275245,
80
+ "minping": 0.07081899999999999,
81
+ "version": 80002,
82
+ "subver": "/SecondClient/",
83
+ "inbound": false,
84
+ "startingheight": 467483,
85
+ "banscore": 0,
86
+ "synced_headers": 467515,
87
+ "synced_blocks": 467515,
88
+ "inflight": [
89
+ ],
90
+ "whitelisted": false
91
+ }
92
+ ]
84
93
  HEREDOC
@@ -29,8 +29,9 @@ describe Pickynode do
29
29
 
30
30
  describe '.add' do
31
31
  it 'should add nodes based on user agent' do
32
- expect(subject).to receive(:bitnodes_snapshot).once
33
- .and_return(BITNODES_SNAPSHOT)
32
+ expect(subject).to receive(:blockchair_snapshot)
33
+ .once
34
+ .and_return(BLOCKCHAIR_SNAPSHOT)
34
35
  expect(subject).to receive(:run_cmd)
35
36
  .with(%(bitcoin-cli addnode "#{ipv6_ip}" "add"))
36
37
  subject.add('Satoshi')
@@ -40,14 +41,15 @@ describe Pickynode do
40
41
  end
41
42
 
42
43
  it 'should return if the filter is falsy' do
43
- expect(subject).to_not receive(:bitnodes_snapshot)
44
+ expect(subject).to_not receive(:blockchair_snapshot)
44
45
  expect(subject).to_not receive(:run_cmd)
45
46
  subject.add(false)
46
47
  subject.add(nil)
47
48
  end
48
49
 
49
50
  it 'should recover gracefully if json is malformed' do
50
- expect(subject).to receive(:bitnodes_snapshot).once
51
+ expect(subject).to receive(:blockchair_snapshot)
52
+ .once
51
53
  .and_return(json_error)
52
54
  expect(subject).to_not receive(:run_cmd)
53
55
  subject.add('Anything')
@@ -62,16 +64,18 @@ describe Pickynode do
62
64
 
63
65
  context 'with a limit' do
64
66
  it 'should respect a limit parameter of 1' do
65
- expect(subject).to receive(:bitnodes_snapshot).once
66
- .and_return(BITNODES_SNAPSHOT)
67
+ expect(subject).to receive(:blockchair_snapshot)
68
+ .once
69
+ .and_return(BLOCKCHAIR_SNAPSHOT)
67
70
  expect(subject).to receive(:run_cmd)
68
71
  .with('bitcoin-cli addnode "88.99.199.87:8333" "add"')
69
72
  subject.add('i', 1)
70
73
  end
71
74
 
72
75
  it 'should respect a limit parameter greater than 1' do
73
- expect(subject).to receive(:bitnodes_snapshot).once
74
- .and_return(BITNODES_SNAPSHOT)
76
+ expect(subject).to receive(:blockchair_snapshot)
77
+ .once
78
+ .and_return(BLOCKCHAIR_SNAPSHOT)
75
79
  expect(subject).to receive(:run_cmd)
76
80
  .with('bitcoin-cli addnode "88.99.199.87:8333" "add"')
77
81
  expect(subject).to receive(:run_cmd)
@@ -84,14 +88,14 @@ describe Pickynode do
84
88
  describe '.ban' do
85
89
  it 'should ban nodes based on user agent' do
86
90
  expect(subject).to receive(:`).once
87
- .and_return(PEER_INFO)
91
+ .and_return(PEER_INFO)
88
92
  expect(URI).to receive(:parse).with('https://131.114.88.218:33422')
89
- .and_call_original
93
+ .and_call_original
90
94
  expect(subject).to receive(:run_cmd)
91
95
  .with('bitcoin-cli setban "131.114.88.218" "add"')
92
96
  subject.ban('FirstClient')
93
97
  expect(URI).to receive(:parse).with("https://#{ipv6_ip}")
94
- .and_call_original
98
+ .and_call_original
95
99
  expect(subject).to receive(:run_cmd)
96
100
  .with(%(bitcoin-cli setban "#{ipv6_ip_no_port}" "add"))
97
101
  subject.ban('SecondClient')
@@ -107,7 +111,7 @@ describe Pickynode do
107
111
 
108
112
  it 'should recover gracefully if json is malformed' do
109
113
  expect(subject).to receive(:`).once
110
- .and_return(json_error)
114
+ .and_return(json_error)
111
115
  expect(subject).to_not receive(:run_cmd)
112
116
  subject.ban('Anything')
113
117
  end
@@ -115,8 +119,9 @@ describe Pickynode do
115
119
 
116
120
  describe '.connect' do
117
121
  it 'should connect to nodes based on user agent' do
118
- expect(subject).to receive(:bitnodes_snapshot).once
119
- .and_return(BITNODES_SNAPSHOT)
122
+ expect(subject).to receive(:blockchair_snapshot)
123
+ .once
124
+ .and_return(BLOCKCHAIR_SNAPSHOT)
120
125
  expect(subject).to receive(:run_cmd)
121
126
  .with('bitcoin-cli addnode "88.99.199.87:8333" "onetry"')
122
127
  subject.connect('Unlimited')
@@ -126,15 +131,15 @@ describe Pickynode do
126
131
  end
127
132
 
128
133
  it 'should return if the filter is falsy' do
129
- expect(subject).to_not receive(:bitnodes_snapshot)
134
+ expect(subject).to_not receive(:blockchair_snapshot)
130
135
  expect(subject).to_not receive(:run_cmd)
131
136
  subject.connect(false)
132
137
  subject.connect(nil)
133
138
  end
134
139
 
135
140
  it 'should recover gracefully if json is malformed' do
136
- expect(subject).to receive(:bitnodes_snapshot).once
137
- .and_return(json_error)
141
+ expect(subject).to receive(:blockchair_snapshot).once
142
+ .and_return(json_error)
138
143
  expect(subject).to_not receive(:run_cmd)
139
144
  subject.connect('Anything')
140
145
  end
@@ -148,16 +153,18 @@ describe Pickynode do
148
153
 
149
154
  context 'with a limit' do
150
155
  it 'should respect a limit parameter of 1' do
151
- expect(subject).to receive(:bitnodes_snapshot).once
152
- .and_return(BITNODES_SNAPSHOT)
156
+ expect(subject).to receive(:blockchair_snapshot)
157
+ .once
158
+ .and_return(BLOCKCHAIR_SNAPSHOT)
153
159
  expect(subject).to receive(:run_cmd)
154
160
  .with('bitcoin-cli addnode "88.99.199.87:8333" "onetry"')
155
161
  subject.connect('i', 1)
156
162
  end
157
163
 
158
164
  it 'should respect a limit parameter greater than 1' do
159
- expect(subject).to receive(:bitnodes_snapshot).once
160
- .and_return(BITNODES_SNAPSHOT)
165
+ expect(subject).to receive(:blockchair_snapshot)
166
+ .once
167
+ .and_return(BLOCKCHAIR_SNAPSHOT)
161
168
  expect(subject).to receive(:run_cmd)
162
169
  .with('bitcoin-cli addnode "88.99.199.87:8333" "onetry"')
163
170
  expect(subject).to receive(:run_cmd)
@@ -170,7 +177,7 @@ describe Pickynode do
170
177
  describe '.disconnect' do
171
178
  it 'should disconnect nodes based on user agent' do
172
179
  expect(subject).to receive(:`).once
173
- .and_return(PEER_INFO)
180
+ .and_return(PEER_INFO)
174
181
  expect(subject).to receive(:run_cmd)
175
182
  .with(%(bitcoin-cli disconnectnode "#{ipv6_ip}"))
176
183
  subject.disconnect('SecondClient')
@@ -188,7 +195,7 @@ describe Pickynode do
188
195
 
189
196
  it 'should recover gracefully if json is malformed' do
190
197
  expect(subject).to receive(:`).once
191
- .and_return(json_error)
198
+ .and_return(json_error)
192
199
  expect(subject).to_not receive(:run_cmd)
193
200
  subject.disconnect('Anything')
194
201
  end
@@ -197,14 +204,14 @@ describe Pickynode do
197
204
  describe '.display' do
198
205
  it 'should display connected nodes' do
199
206
  expect(subject).to receive(:`).once
200
- .and_return(PEER_INFO)
207
+ .and_return(PEER_INFO)
201
208
  expect(subject).to receive(:ap).with(node_hash).and_return(node_hash)
202
209
  expect(subject.display).to eq(node_hash)
203
210
  end
204
211
 
205
212
  it 'should recover gracefully if json is malformed' do
206
213
  expect(subject).to receive(:`).once
207
- .and_return(json_error)
214
+ .and_return(json_error)
208
215
  expect(subject).to receive(:ap).with({}).and_return({})
209
216
  expect(subject.display).to eq({})
210
217
  end
@@ -212,16 +219,16 @@ describe Pickynode do
212
219
 
213
220
  describe '.info' do
214
221
  it 'should display local node info' do
215
- expect(subject).to receive(:`).once
216
- .and_return(NODE_INFO)
222
+ expect(subject).to receive(:`).twice
223
+ .and_return(NODE_INFO)
217
224
  expect(subject).to receive(:ap).with(parsed_node_info)
218
- .and_return(parsed_node_info)
225
+ .and_return(parsed_node_info)
219
226
  expect(subject.info).to eq(parsed_node_info)
220
227
  end
221
228
 
222
229
  it 'should recover gracefully if json is malformed' do
223
- expect(subject).to receive(:`).once
224
- .and_return(json_error)
230
+ expect(subject).to receive(:`).twice
231
+ .and_return(json_error)
225
232
  expect(subject).to receive(:ap).with({}).and_return({})
226
233
  expect(subject.info).to eq({})
227
234
  end
@@ -242,30 +249,31 @@ describe Pickynode do
242
249
  end
243
250
 
244
251
  it 'should call add, connect, ban, disconnect and info' do
245
- expect(subject).to receive(:bitnodes_snapshot).once
246
- .and_return(BITNODES_SNAPSHOT)
252
+ expect(subject).to receive(:blockchair_snapshot)
253
+ .once
254
+ .and_return(BLOCKCHAIR_SNAPSHOT)
247
255
  expect(subject).to receive(:getpeerinfo).once
248
- .and_return(PEER_INFO)
256
+ .and_return(PEER_INFO)
249
257
  expect(subject).to receive(:add).with(opts[:add], opts[:limit])
250
- .and_call_original
258
+ .and_call_original
251
259
  expect(subject).to receive(:connect).with(opts[:connect], opts[:limit])
252
- .and_call_original
260
+ .and_call_original
253
261
  expect(subject).to receive(:ban).with(opts[:ban])
254
- .and_call_original
262
+ .and_call_original
255
263
  expect(subject).to receive(:disconnect).with(opts[:disconnect])
256
- .and_call_original
264
+ .and_call_original
257
265
  expect(subject).to receive(:info)
258
266
  expect(subject).to_not receive(:display)
259
267
  subject.run
260
268
  end
261
269
 
262
270
  it 'should recover gracefully if json is malformed' do
263
- expect(subject).to receive(:bitnodes_snapshot).at_least(1)
264
- .and_return(json_error)
271
+ expect(subject).to receive(:blockchair_snapshot).at_least(1)
272
+ .and_return(json_error)
265
273
  expect(subject).to receive(:getpeerinfo).at_least(1)
266
- .and_return(json_error)
267
- expect(subject).to receive(:`)
268
- .and_return(json_error)
274
+ .and_return(json_error)
275
+ expect(subject).to receive(:`).twice
276
+ .and_return(json_error)
269
277
  expect(subject).to receive(:info)
270
278
  .and_call_original
271
279
  expect(subject).to receive(:ap).with({})
@@ -281,7 +289,7 @@ describe Pickynode do
281
289
 
282
290
  it 'should call display' do
283
291
  expect(subject).to receive(:`).once
284
- .and_return(PEER_INFO)
292
+ .and_return(PEER_INFO)
285
293
  expect(subject).to receive(:ap).with(node_hash).and_return(node_hash)
286
294
  expect(subject).to receive(:display).and_call_original
287
295
  subject.run
@@ -289,7 +297,7 @@ describe Pickynode do
289
297
 
290
298
  it 'should recover gracefully if json is malformed' do
291
299
  expect(subject).to receive(:`).once
292
- .and_return(json_error)
300
+ .and_return(json_error)
293
301
  expect(subject).to_not receive(:run_cmd)
294
302
  expect(subject).to_not receive(:info)
295
303
  expect(subject).to receive(:ap).with({}).and_return({})
@@ -299,9 +307,10 @@ describe Pickynode do
299
307
  end
300
308
 
301
309
  describe 'clear_cache' do
302
- it 'should clear the bitnodes cache' do
303
- expect(subject).to receive(:bitnodes_snapshot).once
304
- .and_return(BITNODES_SNAPSHOT)
310
+ it 'should clear the blockchair cache' do
311
+ expect(subject).to receive(:blockchair_snapshot)
312
+ .once
313
+ .and_return(BLOCKCHAIR_SNAPSHOT)
305
314
  expect(subject).to receive(:run_cmd)
306
315
  .with(%(bitcoin-cli addnode "#{ipv6_ip}" "add"))
307
316
  expect(subject).to receive(:run_cmd)
@@ -309,8 +318,9 @@ describe Pickynode do
309
318
  subject.add('Satoshi')
310
319
  subject.add('Unlimited')
311
320
  subject.clear_cache
312
- expect(subject).to receive(:bitnodes_snapshot).once
313
- .and_return(BITNODES_SNAPSHOT)
321
+ expect(subject).to receive(:blockchair_snapshot)
322
+ .once
323
+ .and_return(BLOCKCHAIR_SNAPSHOT)
314
324
  expect(subject).to receive(:run_cmd)
315
325
  .with(%(bitcoin-cli addnode "#{ipv6_ip}" "add"))
316
326
  subject.add('Satoshi')
@@ -318,11 +328,11 @@ describe Pickynode do
318
328
 
319
329
  it 'should clear the getpeerinfo cache' do
320
330
  expect(subject).to receive(:getpeerinfo).once
321
- .and_return(PEER_INFO)
331
+ .and_return(PEER_INFO)
322
332
  expect(URI).to receive(:parse).with('https://131.114.88.218:33422')
323
- .and_call_original
333
+ .and_call_original
324
334
  expect(URI).to receive(:parse).with(%(https://#{ipv6_ip}))
325
- .and_call_original
335
+ .and_call_original
326
336
  expect(subject).to receive(:run_cmd)
327
337
  .with('bitcoin-cli setban "131.114.88.218" "add"')
328
338
  expect(subject).to receive(:run_cmd)
@@ -331,9 +341,9 @@ describe Pickynode do
331
341
  subject.ban('SecondClient')
332
342
  subject.clear_cache
333
343
  expect(subject).to receive(:getpeerinfo).once
334
- .and_return(PEER_INFO)
344
+ .and_return(PEER_INFO)
335
345
  expect(URI).to receive(:parse).with('https://131.114.88.218:33422')
336
- .and_call_original
346
+ .and_call_original
337
347
  expect(subject).to receive(:run_cmd)
338
348
  .with('bitcoin-cli setban "131.114.88.218" "add"')
339
349
  subject.ban('FirstClient')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pickynode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Ellithorpe
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-05 00:00:00.000000000 Z
11
+ date: 2024-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print
@@ -25,33 +25,47 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.7'
27
27
  - !ruby/object:Gem::Dependency
28
- name: trollop
28
+ name: base64
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.1'
33
+ version: '0.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.1'
40
+ version: '0.2'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec
42
+ name: optimist
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.6'
48
- type: :development
47
+ version: '3.0'
48
+ type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.6'
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ostruct
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.6'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.6'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,20 @@ dependencies:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: '12.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.6'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.6'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: rubocop
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -107,7 +135,6 @@ files:
107
135
  - ".ruby-version"
108
136
  - ".travis.yml"
109
137
  - Gemfile
110
- - Gemfile.lock
111
138
  - LICENSE
112
139
  - README.md
113
140
  - Rakefile
@@ -122,7 +149,7 @@ homepage: http://github.com/zquestz/pickynode
122
149
  licenses:
123
150
  - MIT
124
151
  metadata: {}
125
- post_install_message:
152
+ post_install_message:
126
153
  rdoc_options: []
127
154
  require_paths:
128
155
  - lib
@@ -130,16 +157,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
157
  requirements:
131
158
  - - ">="
132
159
  - !ruby/object:Gem::Version
133
- version: '2.0'
160
+ version: '2.5'
134
161
  required_rubygems_version: !ruby/object:Gem::Requirement
135
162
  requirements:
136
163
  - - ">="
137
164
  - !ruby/object:Gem::Version
138
165
  version: '0'
139
166
  requirements: []
140
- rubyforge_project:
141
- rubygems_version: 2.6.11
142
- signing_key:
167
+ rubygems_version: 3.0.9
168
+ signing_key:
143
169
  specification_version: 4
144
170
  summary: Manage connections to your bitcoin node
145
171
  test_files: []
data/Gemfile.lock DELETED
@@ -1,58 +0,0 @@
1
- GEM
2
- remote: https://rubygems.org/
3
- specs:
4
- ast (2.3.0)
5
- awesome_print (1.7.0)
6
- diff-lcs (1.3)
7
- docile (1.1.5)
8
- json (2.1.0)
9
- parser (2.4.0.0)
10
- ast (~> 2.2)
11
- powerpack (0.1.1)
12
- rainbow (2.2.2)
13
- rake
14
- rake (12.0.0)
15
- rspec (3.6.0)
16
- rspec-core (~> 3.6.0)
17
- rspec-expectations (~> 3.6.0)
18
- rspec-mocks (~> 3.6.0)
19
- rspec-core (3.6.0)
20
- rspec-support (~> 3.6.0)
21
- rspec-expectations (3.6.0)
22
- diff-lcs (>= 1.2.0, < 2.0)
23
- rspec-support (~> 3.6.0)
24
- rspec-mocks (3.6.0)
25
- diff-lcs (>= 1.2.0, < 2.0)
26
- rspec-support (~> 3.6.0)
27
- rspec-support (3.6.0)
28
- rubocop (0.48.1)
29
- parser (>= 2.3.3.1, < 3.0)
30
- powerpack (~> 0.1)
31
- rainbow (>= 1.99.1, < 3.0)
32
- ruby-progressbar (~> 1.7)
33
- unicode-display_width (~> 1.0, >= 1.0.1)
34
- ruby-progressbar (1.8.1)
35
- simplecov (0.14.1)
36
- docile (~> 1.1.0)
37
- json (>= 1.8, < 3)
38
- simplecov-html (~> 0.10.0)
39
- simplecov-html (0.10.1)
40
- trollop (2.1.2)
41
- unicode-display_width (1.2.1)
42
-
43
- PLATFORMS
44
- ruby
45
-
46
- DEPENDENCIES
47
- awesome_print (~> 1.7)
48
- rake (~> 12.0)
49
- rspec (~> 3.6)
50
- rubocop (~> 0.48)
51
- simplecov (~> 0.14)
52
- trollop (~> 2.1)
53
-
54
- RUBY VERSION
55
- ruby 2.3.4p301
56
-
57
- BUNDLED WITH
58
- 1.14.6