abot-whitelist 0.2.0 → 0.3.1

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: 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