abot-whitelist 0.2.0 → 0.3.1

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: 87bf91fb9d03999272df0b4acac7cdaa84388253b42cb4c42730289095ccea4b
4
- data.tar.gz: 13664637d383cc08486b67df9d257e15d156b4f712f225722eae949dc2f76845
3
+ metadata.gz: d399811d901d4890fefcd6db8442638ee60e3bd05cf37daab990813e0a630fed
4
+ data.tar.gz: ee0dce6fb6bf1d9e444d43ec3a6bf63123b84135b26c1a54c6dfb5acbe1e0958
5
5
  SHA512:
6
- metadata.gz: 123fff02723291bae6eeca4d8ec8bfc6bc21bc74f23d1b171884555451702d33fe57fad9d21529b350b37b91b99a1a469854d3444e630afbba83954447cda359
7
- data.tar.gz: 86f9135baf85bd8df12ffc3b2c66ee980114ed35555cc86fbe9084597318dae1692588505e151123e86e8f91259393e4fbd0895a88c2b2d7f6a62c09ba3d26ab
6
+ metadata.gz: 7788fdefec41dc9397e9a494f674e0e49da88aebf547b129c6a7090745cba60c9ad68447f02a24e4797c5339e2bc0e3c383682908ad10d75a4321273f289f92b
7
+ data.tar.gz: d836ccacf75442c67dba3ba95c2e1c0db0f4d6d39ab518d2af1517a0f160358e5ca8fa5e589788e8939aca8797723255981f39d899a6f26b96033d78aebb73d0
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  gem 'activerecord', '~> 6.1.3'
4
4
  gem 'binance-ruby', '~> 1.3.1'
5
+ gem 'coingecko_ruby', '~> 0.4.2'
@@ -34,5 +34,6 @@ Gem::Specification.new do |spec|
34
34
 
35
35
  spec.add_dependency "activerecord", '~> 6.1.3'
36
36
  spec.add_dependency "binance-ruby", '~> 1.3.1'
37
+ spec.add_dependency 'coingecko_ruby', '~> 0.4.2'
37
38
 
38
39
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abot
4
+ module Whitelist
5
+ class AbotConfigSite
6
+ include HTTParty
7
+
8
+ base_uri 'https://abot-config.ru'
9
+
10
+ def list(list_number)
11
+ path = "/coins/whitelist-#{list_number}.txt"
12
+ response = self.class.get(path)
13
+
14
+ if response.code == 200
15
+ response.body.split(' ') || ''
16
+ else
17
+ raise "get base whitelist from #{self.class.base_uri} error"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abot
4
+ module Whitelist
5
+ class Base
6
+ attr_reader :top, :list_number
7
+
8
+ DEFAULT_COINS = %w[one unfi sol].freeze
9
+ FIAT = %w[usdt busd aud bidr brl eur gbr rub try tusd usdc dai idrt pax uah ngn vai bvnd].freeze
10
+ BLACK_LIST = %w[fun xvs aion btc].freeze
11
+
12
+ def self.black_coins
13
+ FIAT + BLACK_LIST
14
+ end
15
+
16
+ def initialize(options)
17
+ @top = options[:top]
18
+ @list_number = options[:list_number]
19
+ end
20
+
21
+ def process!
22
+ coins_list = top_list
23
+ if list_number
24
+ base_list = Abot::Whitelist::AbotConfigSite.new.list(list_number)
25
+ coins_list = coins_list.map { |m| base_list.include?(m) ? m : nil }.compact
26
+
27
+ puts "base list: #{base_list}\n"
28
+ puts "coins (count = #{coins_list.count}) from the base list in the top #{top} by capitalization:"
29
+ else
30
+ puts "coins (count = #{coins_list.count}) in the top #{top} by capitalization:"
31
+ end
32
+
33
+ puts coins_list.join(' ')
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abot
4
+ module Whitelist
5
+ class Binance < Base
6
+ attr_reader :top, :list_number
7
+
8
+ include HTTParty
9
+ base_uri 'https://www.binance.com'
10
+
11
+ def self.list_all_usdt_coins
12
+ usdt_coins.map { |m| black_coins.include?(m[:b].downcase) ? nil : m[:b].downcase }.compact
13
+ end
14
+
15
+ def self.usdt_coins
16
+ begin
17
+ JSON.parse(products, symbolize_names: true)[:data].select { |s| s[:q] == 'USDT' }
18
+ rescue JSON::ParserError => error
19
+ # binance 500 errors are html format
20
+ raise Error.new(message: error)
21
+ end
22
+ end
23
+
24
+ def self.products
25
+ path = '/exchange-api/v2/public/asset-service/product/get-products'
26
+ get(path).body
27
+ end
28
+
29
+ def top_list
30
+ all_coins = self.class.usdt_coins.map { |s| [s[:b], (s[:cs].to_f * s[:c].to_f)] }
31
+ .sort_by { |s| s[1] }
32
+ .reverse
33
+ .map { |m| m[0] }
34
+ result = (all_coins - FIAT - BLACK_LIST - DEFAULT_COINS)[0..((top - 1) - DEFAULT_COINS.count)]
35
+ (result + DEFAULT_COINS).map(&:upcase)
36
+ end
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'abot_config_site'
4
+ require 'coingecko_ruby'
5
+
6
+ module Abot
7
+ module Whitelist
8
+ class Coingecko < Base
9
+ attr_reader :client, :top, :list_number
10
+
11
+ DIF_COINS = {
12
+ 'iota' => 'miota',
13
+ 'data' => 'xdata',
14
+ }.freeze
15
+
16
+ def initialize(options)
17
+ @client = CoingeckoRuby::Client.new
18
+
19
+ super(options)
20
+ end
21
+
22
+ def top_list
23
+ coins_ids = []
24
+ list_all_usdt_coins = Binance.list_all_usdt_coins.map do |m|
25
+ DIF_COINS.find { |k, v| k == m }&.dig(1) || m
26
+ end
27
+
28
+ list_all_usdt_coins.each do |coin|
29
+ decorated_all_coins[coin]&.each { |e| coins_ids << e }
30
+ decorated_all_coins[coin.upcase]&.each { |e| coins_ids << e }
31
+ end
32
+ info = coins_info(coins_ids)
33
+ info.keys[0...top].map(&:upcase)
34
+ end
35
+
36
+ def coins_info(coins)
37
+ info = client.markets(coins.join(', '), vs_currency: 'gbp')
38
+ result = {}
39
+ info.each do |m|
40
+ if result[m['symbol']].nil? || (!m['market_cap_rank'].nil? && result[m['symbol']].to_i > m['market_cap_rank'].to_i)
41
+ result[m['symbol'].downcase] = m['market_cap_rank']
42
+ end
43
+ end
44
+
45
+ DIF_COINS.each { |k, v| result[k] = result.delete v }
46
+ result = result.sort_by { |_, v| v.nil? ? 100_000 : v }.to_h
47
+
48
+ no_rank_coins(result)
49
+ all_usdt_coins(result)
50
+
51
+ result
52
+ end
53
+
54
+ def all_coins
55
+ @all_coins ||= client.coins_list
56
+ end
57
+
58
+ private
59
+
60
+ def no_rank_coins(list)
61
+ puts "No rank coins: #{list.select { |_, v| v.nil? }.keys.map(&:upcase).join(', ')}\n\n"
62
+ end
63
+
64
+ def all_usdt_coins(list)
65
+ puts "Rank all Binance USDT coins : #{list.map { |k, v| "#{k.upcase}-#{v}" }.join('; ')}\n\n"
66
+ end
67
+
68
+ def decorated_all_coins
69
+ return @decorated_all_coins if @decorated_all_coins
70
+
71
+ @decorated_all_coins = {}
72
+ all_coins.each do |m|
73
+ @decorated_all_coins["#{m['symbol']}"] ||= []
74
+ unless @decorated_all_coins["#{m['symbol']}"].include?(m['id'])
75
+ (@decorated_all_coins["#{m['symbol']}"] << m['id'])
76
+ end
77
+ end
78
+ @decorated_all_coins
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -1,5 +1,5 @@
1
1
  module Abot
2
2
  module Whitelist
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.1"
4
4
  end
5
5
  end
@@ -3,8 +3,11 @@
3
3
  require 'active_record'
4
4
  require 'binance-ruby'
5
5
 
6
+ require_relative 'whitelist/abot_config_site'
6
7
  require_relative 'whitelist/option_parser'
7
- require_relative 'whitelist/binance_cap'
8
+ require_relative 'whitelist/base'
9
+ require_relative 'whitelist/binance'
10
+ require_relative 'whitelist/coingecko'
8
11
  require_relative 'whitelist/version'
9
12
 
10
13
  module Abot
@@ -27,15 +30,37 @@ module Abot
27
30
  :top, '--top=number',
28
31
  'Число монет (ТОП по капитализации)',
29
32
  )
33
+
34
+ parser.add_option(
35
+ :api, '--api=string',
36
+ 'Api: Binance, Coingecko',
37
+ )
30
38
  end.final!
31
39
 
32
- list_number = Whitelist::OptionParser.instance.options[:list_number].to_i
33
- top_number = (Whitelist::OptionParser.instance.options[:top] || 100).to_i
40
+ case opts[:api].downcase
41
+ when 'binance'
42
+ Abot::Whitelist::Binance.new(opts).process!
43
+ when 'coingecko'
44
+ Abot::Whitelist::Coingecko.new(opts).process!
45
+ else
46
+ # nothing
47
+ end
48
+ end
34
49
 
50
+ private
51
+
52
+ def opts
53
+ top_number = (Whitelist::OptionParser.instance.options[:top] || 150).to_i
35
54
  raise 'top is wrong' unless top_number.positive?
36
55
 
37
- base_list = Abot::Whitelist::BaseWhitelist.base_whitelist(list_number: list_number) if list_number.positive?
38
- BinanceCap.send_req(base_list: base_list, top_number: top_number)
56
+ api = Whitelist::OptionParser.instance.options[:api]&.downcase || 'coingecko'
57
+ raise 'api must be Binance, Coingecko' unless ['binance', 'coingecko'].include?(api)
58
+
59
+ {
60
+ list_number: Whitelist::OptionParser.instance.options[:list_number],
61
+ top: top_number,
62
+ api: api,
63
+ }
39
64
  end
40
65
  end
41
66
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abot-whitelist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - w_dmitrii
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-24 00:00:00.000000000 Z
11
+ date: 2021-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 1.3.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: coingecko_ruby
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.4.2
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.4.2
83
97
  description:
84
98
  email:
85
99
  - wiz.work2021@gmail.com
@@ -95,8 +109,10 @@ files:
95
109
  - abot-whitelist.gemspec
96
110
  - exe/abot-whitelist
97
111
  - lib/abot/whitelist.rb
98
- - lib/abot/whitelist/base_whitelist.rb
99
- - lib/abot/whitelist/binance_cap.rb
112
+ - lib/abot/whitelist/abot_config_site.rb
113
+ - lib/abot/whitelist/base.rb
114
+ - lib/abot/whitelist/binance.rb
115
+ - lib/abot/whitelist/coingecko.rb
100
116
  - lib/abot/whitelist/option_parser.rb
101
117
  - lib/abot/whitelist/version.rb
102
118
  - spec/abot/whitelist_spec.rb
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Abot
4
- module Whitelist
5
- class BaseWhitelist
6
- include HTTParty
7
-
8
- class << self
9
- def base_whitelist(list_number:)
10
- self.base_uri 'https://abot-config.ru'
11
-
12
- path = "/coins/whitelist-#{list_number}.txt"
13
- response = get(path)
14
-
15
- if response.code == 200
16
- response.body.split(' ') || ''
17
- else
18
- raise "get base whitelist from #{base_uri} error"
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative 'base_whitelist'
3
-
4
- module Abot
5
- module Whitelist
6
- class BinanceCap
7
- include HTTParty
8
-
9
- DEFAULT_COINS = %w[ONE UNFI SOL].freeze
10
- FIAT = %w[USDT BUSD AUD BIDR BRL EUR GBR RUB TRY TUSD USDC DAI IDRT PAX UAH NGN VAI BVND].freeze
11
- BLACK_LIST = %w[FUN XVS AION BTC].freeze
12
-
13
- class << self
14
- def send_req(base_list:, top_number:)
15
- self.base_uri 'https://www.binance.com'
16
-
17
- path = '/exchange-api/v2/public/asset-service/product/get-products'
18
- response = get(path)
19
- process!(response: response || '{}', base_list: base_list, top_number: top_number)
20
- end
21
-
22
- private
23
-
24
- def process!(response:, base_list:, top_number:)
25
- result = top(response: response, top_number: top_number)
26
- if base_list
27
- result = result.map { |m| base_list.include?(m) ? m : nil }.compact
28
-
29
- puts "base list: #{base_list}"
30
- puts '+++++++++++++++++++++++++++++++++++++++++++++'
31
- puts "coins (count = #{result.count}) from the base list in the top #{top_number} by capitalization:"
32
- else
33
- puts "coins (count = #{result.count}) in the top #{top_number} by capitalization:"
34
- end
35
-
36
- puts result.join(' ')
37
- end
38
-
39
- def top(response:, top_number:)
40
- all_coins = usdt_coins(response: response).map { |s| [s[:b], (s[:cs].to_f * s[:c].to_f)] }
41
- .sort_by { |s| s[1] }
42
- .reverse
43
- .map { |m| m[0] }
44
- result = (all_coins - FIAT - BLACK_LIST)[0..((top_number - 1) - DEFAULT_COINS.count)]
45
- result + DEFAULT_COINS
46
- end
47
-
48
- def usdt_coins(response:)
49
- serialized_response(response: response)[:data].select { |s| s[:q] == 'USDT' }
50
- end
51
-
52
- def serialized_response(response:)
53
- begin
54
- JSON.parse(response.body, symbolize_names: true)
55
- rescue JSON::ParserError => error
56
- # binance 500 errors are html format
57
- raise Error.new(message: error)
58
- end
59
- end
60
- end
61
- end
62
- end
63
- end