ctfc 0.3.3 → 1.0.0.alpha

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: 9eb6a110a8c9249570c3581febbeda07c970d4265e2f4e28c72e63cfd3007e58
4
- data.tar.gz: 291e835ae45d67bbc37ac7eaad33fbf74e581e21c5e4e760dcca39acb8cbd8ab
3
+ metadata.gz: f2aa46b7e28383d2845d81ddeed7173ac7423e6e960dea6ffb4f37ba5e536969
4
+ data.tar.gz: 86ecfff9bb989a17054570ce600ea70e35c71fb1b01ce34e32265c010efa6e44
5
5
  SHA512:
6
- metadata.gz: 624349dc7c81ec34cfa33d46869482fab91f2d8e02f57a3723b220135e3db4ce2fe607d738fdcd565b91b22dc342c6fe342f22af9a55ae4b90e4be50b0cd6d18
7
- data.tar.gz: b051e5169a7c2cf0724c9d2af55477731e8dc5163e04951c9d5f333278e064b2ec95b28d8b932018eeeb9a89dfc8b9c4e6bc8d9c37b13c7d90cc97633378c953
6
+ metadata.gz: cacd0718b90b741a18ddf4199b9ceb23a49fcf63505e741c2c55c40183b0ae40979192b2e875046424db9a0dccee2df04ce8e9973a0be6b90236d395297fd2b3
7
+ data.tar.gz: 12c0ae246495fde8927693ee626d198268d1686483d4ed2e02494c35230511537b3e41030b92eae25278d6b709a12e2ba3e80fe38ab7f2322342850d93635441
data/LICENSE CHANGED
@@ -1,3 +1,9 @@
1
+ ##
2
+ # CTFC gem is copyrighted under MIT license.
3
+ # From version `0.4.1`, first stable Open Source version, gem `colorize` was removed
4
+ # to keep it all under MIT.
5
+ ##
6
+
1
7
  MIT License
2
8
 
3
9
  Copyright (c) 2022 alx3dev
data/README.md CHANGED
@@ -1,158 +1 @@
1
- # About
2
- Convert any crypto to fiat currency, gather all data and/or save in `.csv` table.
3
- For now only prices are printed/saved, while all data remain easily accessible from variable (for developers).
4
-
5
-
6
- # How to install
7
- Make sure you have ruby and git installed
8
-
9
- Install from source:
10
- ```bash
11
- git clone https://github.com/alx3dev/ctfc.git
12
- cd ctfc && bundle install
13
- ```
14
-
15
- Install from rubygems:
16
-
17
- ```bash
18
- gem install ctfc
19
- ```
20
- # How to run
21
- - **Read documentation on:** https://rubydoc.info/gems/ctfc/0.3.1/CTFC/Data
22
-
23
- ```bash
24
- ruby bin/ctfc fiat_1 fiat_2 fiat_3
25
- ```
26
-
27
- This command also accept multiple arguments:
28
-
29
- - `--no-save` - do not save `.csv.` output
30
- - `--no-print` - do not print terminal output
31
- - `--coins` - coins to scrap (default: BTC, LTC, XMR, ETH, BCH, ZEC )
32
- - `--help` - help menu
33
-
34
-
35
- # Script Examples
36
- 1 - Run script without arguments (default options)
37
-
38
- ```ruby
39
- ruby bin/ctfc
40
-
41
- return:
42
- print EUR rates for default coins (BTC, LTC, XMR, ETH, BCH, ZEC)
43
- do not save '.csv' table
44
- ```
45
-
46
-
47
- 2 - Add fiat currencies as arguments
48
-
49
- ```ruby
50
- ruby bin/ctfc eur usd rsd
51
-
52
- => return:
53
- print EUR, USD, RSD rates for default coins
54
- save data in '.csv' table with pattern: 'crypto_#{CURRENCY}.csv'
55
- -> './crypto_eur.csv', './crypto_usd.csv', './crypto_rsd.csv'
56
- ```
57
-
58
- 3 - Use `--no-save` and/or `--no-print`
59
-
60
- ```ruby
61
- ruby bin/ctfc eur --no-print --coins btc xmr ltc
62
-
63
- => return:
64
- save EUR rates for BTC, XMR and LTC
65
- do not print output
66
-
67
-
68
- ruby bin/ctfc rsd --no-save --coins btc xmr
69
-
70
- => return:
71
- print RSD rates for BTC and XMR
72
-
73
- ```
74
-
75
-
76
- # Developer Examples
77
- ```ruby
78
- # define coins to scrap
79
- COINS = %w[ BTC XMR LTC ETH ]
80
-
81
- # initialize Data class
82
- @data = Ctfc.new :eur, save: false, print: false, coins: COINS
83
- => return Ctfc object to work with
84
- => #<Ctfc:0x000055b5c8b61a38 @coins=["BTC", "LTC", "XMR", "ETH", "BCH", "ZEC"], @fiat="EUR", @print=true, @save=true>
85
-
86
- # execute request
87
- @data.get
88
- => return Hash with upcase string coins as keys, and float prices
89
- => {"BTC"=>36760.11, "XMR"=>169.55, "LTC"=>114.4, "ETH"=>2746.22}
90
-
91
- # now you can use ::Data instance methods
92
- @data.response
93
- => return RestClient response to cryptocomare API
94
- => <RestClient::Response 200 "{\"RAW\":{\"BT...">
95
-
96
- # check request url
97
- @data.url
98
- => return Cryptocompare API url
99
- => "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=BTC&fsyms=LTC&fsyms=XMR&fsyms=ETH&fsyms=BCH&fsyms=ZEC&tsyms=EUR"
100
-
101
- # name of csv table (saved in working directory)
102
- @data.table
103
- => return '.csv' table name
104
- => 'ctfc_eur.csv'
105
-
106
- # array of coins to work with
107
- @data.coins
108
- => return coins for scrap, also allow setter method @data.coins = [...]
109
- => ['BTC', 'XMR', 'LTC', 'ETH']
110
-
111
- # get all data about all coins (json api response)
112
- @data.data
113
- => return all data returned by cryptocompare API
114
- => {"RAW"=>
115
- {"BTC"=>
116
- {"EUR"=>
117
- {"TYPE"=>"5",
118
- "MARKET"=>"CCCAGG",
119
- "FROMSYMBOL"=>"BTC",
120
- "TOSYMBOL"=>"EUR",
121
- "FLAGS"=>"2049",
122
- "PRICE"=>33851.17,
123
- "LASTUPDATE"=>1642773847,
124
- "MEDIAN"=>33853.8,
125
- "LASTVOLUME"=>0.1,
126
- "LASTVOLUMETO"=>3384.3676,
127
- "LASTTRADEID"=>"2024043",
128
- ... ... ... ... ... ... ...
129
-
130
-
131
- TO BE CONTINIUED ...
132
- ```
133
-
134
- **Class methods as shortcuts:**
135
-
136
- ```ruby
137
- # get default coins in EUR, save output without printing
138
- prices = Ctfc.to :eur, print: false
139
-
140
- # get default coins in RSD, print output, don't save
141
- Ctfc.to :rsd, save: false
142
-
143
- # For those who don't like name `Ctfc`, you can use `Crypto` too:
144
- prices = Crypto.to :eur, coins: %w[BTC XMR]
145
- ```
146
-
147
- # Contribution
148
- Any contribution is highly appreciated, as long as you follow Code of Conduct.
149
-
150
- - Fork repository
151
- - Make your changes
152
- - Submit pull request
153
-
154
- # License
155
- Don't be a dick - it's MIT.
156
-
157
- # To-Do:
158
- See **Projects**
1
+ This is development branch, testing code before merge.
data/bin/ctfc CHANGED
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative '../lib/ctfc'
5
4
  require 'optimist'
5
+ require_relative '../lib/ctfc'
6
+ require_relative '../lib/ctfc/helpers/cli'
7
+
8
+ COINS = %w[BTC XMR ETH LTC].freeze
6
9
 
7
10
  opts = Optimist.options do
8
- version "Software Version: #{CTFC::VERSION}"
11
+ version "Crypto To Fiat Currency\nGem Version: #{CTFC::VERSION}"
9
12
 
10
13
  banner ''
11
14
  banner ' Enter fiat currencies with/out additional arguments:'
@@ -14,26 +17,38 @@ opts = Optimist.options do
14
17
  banner ' ruby bin/ctfc eur usd --no-save --coins btc xmr ltc'
15
18
  banner ''
16
19
 
17
- opt :coins, 'Set crypto coins', default: CTFC::CONFIG::COINS
18
- opt :no_save, "Do not save '.csv' output"
19
- opt :no_print, 'Do not print terminal output'
20
+ opt :coins, 'Set crypto coins', default: COINS
21
+ opt :save, "Save prices in '.csv' table", default: false
22
+ opt :export, "Export all data in '.json' file", default: false
23
+ opt :no_print, 'Do not print terminal output', default: false
24
+ opt :source, 'Set source to extract data', default: 'cryptocompare'
25
+ opt :loop, 'Run script N times', default: 1, type: :integer
26
+ opt :wait, 'Wait N seconds between loop', default: 0, type: :integer
20
27
  end
21
28
 
22
- save = opts[:no_save] ? false : true
23
- print = opts[:no_print] ? false : true
29
+ coins = opts[:coins]
30
+ source = opts[:source]
31
+ save = opts[:save]
32
+ export = opts[:export]
33
+ print = true unless opts[:no_print]
24
34
 
25
35
  if ARGV.empty?
36
+ prices = Crypto.to :usd, coins, source.to_sym, save: save, export: export
37
+ Cli.print_output :USD, prices if print
38
+ else
39
+ opts[:loop].times do
40
+ ARGV.each do |fiat|
41
+ next if opts.include?(fiat.downcase)
26
42
 
27
- Crypto.to :eur, save: false, print: true
43
+ prices = Crypto.to fiat, coins, source.to_sym, save: save, export: export
44
+ next unless print
28
45
 
29
- else
46
+ system 'clear' or system 'cls'
47
+ Cli.print_output fiat, prices
48
+ end
30
49
 
31
- ARGV.each do |fiat|
32
- next if opts.include? fiat.downcase
50
+ next unless opts[:loop] > 1
33
51
 
34
- Ctfc.to(fiat,
35
- save: save,
36
- print: print,
37
- coins: opts.coins)
52
+ sleep opts[:wait]
38
53
  end
39
54
  end
data/ctfc.gemspec CHANGED
@@ -1,37 +1,58 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative './lib/ctfc/version'
4
+ require_relative './lib/ctfc/helpers/list'
4
5
 
5
6
  Gem::Specification.new do |s|
6
7
  s.name = 'ctfc'
7
8
  s.version = CTFC::VERSION
8
- s.summary = 'Crypto to Fiat currency data gathering'
9
- s.description = 'Convert any crypto to fiat currency and/or save in csv table.'
9
+ s.summary = 'Cryptocurrency data gathering gem. Scrap and save as CSV and/or JSON.'
10
+ s.description = <<~DESCRIPTION
11
+ == DEVELOPMENT VERSION==
12
+ Cryptocurrency data gathering gem. Get data from multiple APIs, print and
13
+ save output as you wish. Run script from terminal, or use in another app.
14
+ Class-template based, easy to extend to add more sources. MIT License.
15
+ DESCRIPTION
10
16
 
11
17
  s.license = 'MIT'
12
18
  s.authors = 'alx3dev'
13
19
  s.homepage = 'https://github.com/alx3dev/ctfc'
14
20
 
15
21
  s.bindir = 'bin'
16
- s.require_paths = ['lib']
17
- s.executables = ['ctfc']
22
+ s.require_paths = 'lib'
23
+ s.executables = 'ctfc'
18
24
 
19
25
  s.metadata['homepage_uri'] = 'https://github.com/alx3dev/ctfc'
20
26
  s.metadata['source_code_uri'] = 'https://github.com/alx3dev/ctfc'
21
27
  s.metadata['bug_tracker_uri'] = 'https://github.com/alx3dev/ctfc/issues'
28
+ s.metadata['changelog_uri'] = 'https://github.com/alx3dev/ctfc/CHANGELOG.md'
22
29
  s.metadata['documentation_uri'] = "https://rubydoc.info/gems/#{s.name}/#{s.version}"
30
+ s.metadata['license_uri'] = 'https://github.com/alx3dev/ctfc/LICENSE'
23
31
  s.metadata['rubygems_mfa_required'] = 'true'
24
32
 
25
- s.files = ['bin/ctfc', 'bin/console', 'lib/ctfc.rb', 'LICENSE', 'README.md', 'ctfc.gemspec',
26
- 'lib/ctfc/config.rb', 'lib/ctfc/version.rb', 'lib/ctfc/base.rb']
27
-
28
- s.required_ruby_version = '>= 3.0.1'
29
-
30
- s.add_runtime_dependency 'colorize', '~> 0.8.1'
33
+ s.files = %w[ lib/ctfc.rb
34
+ lib/ctfc/client.rb
35
+ lib/ctfc/export.rb
36
+ lib/ctfc/version.rb
37
+ lib/ctfc/api.rb
38
+ lib/ctfc/api/apitemplate.rb
39
+ LICENSE
40
+ README.md
41
+ ctfc.gemspec]
42
+
43
+ # auto-add sources in api dir
44
+ List.source_files.select do |source|
45
+ file = "lib/ctfc/api/#{source}"
46
+ s.files += [file]
47
+ end
48
+
49
+ s.required_ruby_version = '> 2.7', '< 3.2'
50
+
51
+ s.add_runtime_dependency 'kolorit', '~> 0.2'
31
52
  s.add_runtime_dependency 'optimist', '~> 3.0.1'
32
53
  s.add_runtime_dependency 'rest-client', '~> 2.1.0'
33
54
 
34
- s.add_development_dependency 'bundler', '~> 2.2.9'
35
- s.add_development_dependency 'pry', '~> 0.14.1'
36
- s.add_development_dependency 'rake', '~> 13.0.3'
55
+ s.add_development_dependency 'bundler', '~> 2.3'
56
+ s.add_development_dependency 'pry', '~> 0.14'
57
+ s.add_development_dependency 'rake', '~> 13.0'
37
58
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rest-client'
4
+ require 'json'
5
+
6
+ module CTFC
7
+ module API
8
+ # Template for other sources. Every file in api dir should extend this class.
9
+ # Automatically call method #process to send api request after initialization.
10
+ # This mean every source should include method #process, that will be executed
11
+ # after initialization.
12
+ #
13
+ # @see CTFC::API
14
+ # @see CTFC::API::Cryptocompare
15
+ #
16
+ class ApiTemplate
17
+ attr_reader :response
18
+
19
+ # max number of requests to send
20
+ MAX_RETRY = 3
21
+
22
+ # Construct response hash from given arguments, and start counting requests.
23
+ # Call private method #process to extract data from web.
24
+ #
25
+ # @example Send request to cryptocompare
26
+ # crypto = Cryptocompare.new :eur, %w[BTC XMR]
27
+ #
28
+ # @param [Symbol] fiat **Required**. Fiat currency to use for conversion.
29
+ # @param [Array] coins **Required**. Array of coins to extract data.
30
+ #
31
+ # @return [Object] Source instance.
32
+ #
33
+ def initialize(fiat, coins)
34
+ @response = { fiat: fiat, coins: coins, success: false }
35
+ @counter = 0
36
+ process
37
+ end
38
+
39
+ # Initialize new instance, send request and return response hash.
40
+ # @example
41
+ # Cryptocompare[:eur, %w[BTC XMR]]
42
+ #
43
+ # @param [Symbol] fiat **Required**. Fiat currency.
44
+ # @param [Array] coins **Required**. Cryptocurrency coins.
45
+ #
46
+ # @return [Hash] Response hash object.
47
+ #
48
+ def self.[](fiat, coins)
49
+ new(fiat, coins).response
50
+ end
51
+
52
+ private
53
+
54
+ def process
55
+ return false unless response[:fiat] && response[:coins]
56
+ end
57
+
58
+ def success!(set: true)
59
+ @counter = 0 if set == true
60
+ @response[:success] = set
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'apitemplate' unless defined? CTFC::API::ApiTemplate
4
+
5
+ module CTFC
6
+ module API
7
+ # Source file for cryptocompare api.
8
+ # Initialize will automatically call #process,
9
+ # to send request after all attributes and variables are configured.
10
+ #
11
+ # @see CTFC::API::ApiTemplate
12
+ #
13
+ class Cryptocompare < ApiTemplate
14
+ # Cryptocompare API base url, where we add coins and fiat currency.
15
+ BASE_URL = 'https://min-api.cryptocompare.com/data/pricemultifull?'
16
+
17
+ private
18
+
19
+ def process
20
+ super
21
+ uri = ''
22
+ response[:coins].collect do |coin|
23
+ uri += "fsyms=#{coin}&" unless uri.include? coin
24
+ end
25
+ uri += "tsyms=#{response[:fiat]}"
26
+ @response[:uri] = BASE_URL + uri
27
+ do_rest_request
28
+ end
29
+
30
+ def do_rest_request(time = Time.now)
31
+ rest = RestClient.get(response[:uri])
32
+ success! if rest.code == 200
33
+ process_json_data JSON.parse(rest), time
34
+ rescue StandardError => e
35
+ success! set: false
36
+ if (@counter += 1) > MAX_RETRY
37
+ puts e.message
38
+ else
39
+ retry
40
+ end
41
+ end
42
+
43
+ def process_json_data(data, time)
44
+ fiat = response[:fiat]
45
+ prices = {}
46
+ response[:coins].each do |coin|
47
+ value = data['RAW'][coin.upcase][fiat.to_s.upcase]['PRICE'].round(2)
48
+ prices[coin] = value
49
+ end
50
+ @response.merge!(time: time.to_s, prices: prices, data: data)
51
+ end
52
+ end
53
+ end
54
+ end
data/lib/ctfc/api.rb ADDED
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Benchmark say it's faster to use **unless defined?** if we require file
4
+ # on multiple locations
5
+
6
+ require_relative 'api/apitemplate' unless defined? CTFC::API::ApiTemplate
7
+ require_relative 'helpers/list' unless defined? List
8
+
9
+ # automatically require new apis
10
+ List.sources.select { |source| require_relative "api/#{source}" }
11
+
12
+ module CTFC
13
+ #
14
+ # Keep sources to extract data. Each source has to be a class,
15
+ # named as API domain, extending ApiTemplate. This will automatically
16
+ # make it available in Client, but also added to .gemspec.
17
+ #
18
+ # @see CTFC::API::ApiTemplate
19
+ # @see CTFC::API::Cryptocompare
20
+ #
21
+ # @example Add a new source to extract data:
22
+ # # make file new_source.rb
23
+ # class NewSource < ApiTemplate
24
+ #
25
+ # private
26
+ #
27
+ # def process
28
+ # # check response hash for persistence of fiat and coins
29
+ # super
30
+ # # write method to scrap data from NewSource
31
+ # end
32
+ # end
33
+ #
34
+ module API
35
+ end
36
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'api'
4
+ require_relative 'export'
5
+
6
+ module CTFC
7
+ #
8
+ # Client allow us to get data from our sources, and to
9
+ # manipulate with that data. While other classes are mostly
10
+ # used by each-other, Client is mostly used directly by user.
11
+ #
12
+ class Client
13
+ attr_reader :config, :response, :prices
14
+
15
+ #
16
+ # Choose fiat currency, coins and source for new client.
17
+ # @example Initialize new **EUR** client
18
+ # client = CTFC::Client.new :eur, %w[BTC XMR LTC ETH]
19
+ #
20
+ # @param [Symbol] currency **Required**. Set fiat currency.
21
+ # @param [Array] coins **Required**. Set crypto coins.
22
+ # @param [Symbol] source Optional. Source for data extraction.
23
+ # @param [Hash] opts Options hash for additional configuration.
24
+ #
25
+ # @option opts [Symbol] source Set source to extract data.
26
+ # @option opts [Boolean] save Set option to save prices in csv table.
27
+ # @option opts [Boolean] export Set option to export all data in json file.
28
+ #
29
+ # @return [Client] Client instance.
30
+ #
31
+ def initialize(fiat, coins, source = nil, opts = {})
32
+ @config = {
33
+ fiat: fiat,
34
+ coins: coins,
35
+ source: source || opts[:source],
36
+ save: [nil, true].include?(opts[:save]),
37
+ export: opts[:export].is_a?(TrueClass)
38
+ }
39
+ end
40
+
41
+ # Scrap data from source.
42
+ # @example
43
+ # client.get :cryptocompare
44
+ #
45
+ # @param [Symbol] source Source to send api request
46
+ # @return [Hash] Hash of fiat values for scrapped coins
47
+ #
48
+ def get(source = nil)
49
+ source ||= config[:source]
50
+ send_api_request(source)
51
+ if success?
52
+ Export.to_csv(source, response) if save?
53
+ Export.to_json(source, response) if export?
54
+ end
55
+ @prices = response[:prices]
56
+ end
57
+
58
+ # Source for data extraction.
59
+ # @return [Symbol]
60
+ #
61
+ def source
62
+ config[:source]
63
+ end
64
+
65
+ # Set source for data extraction.
66
+ # @return [Symbol]
67
+ #
68
+ def source=(param)
69
+ @config[:source] = param
70
+ end
71
+
72
+ # Check if csv output will be saved after request.
73
+ # @return [Boolean]
74
+ #
75
+ def save?
76
+ config[:save].is_a?(TrueClass)
77
+ end
78
+
79
+ # Change option to save prices in csv table after request.
80
+ # @return [Boolean]
81
+ #
82
+ def save=(opt)
83
+ @config[:save] = opt.is_a?(TrueClass)
84
+ end
85
+
86
+ # Check if json output will be exported after request.
87
+ # @return [Boolean]
88
+ #
89
+ def export?
90
+ config[:export].is_a?(TrueClass)
91
+ end
92
+
93
+ # Change option to export all data in json file after request.
94
+ # @return [Boolean]
95
+ #
96
+ def export=(opt)
97
+ @config[:export] = opt.is_a?(TrueClass)
98
+ end
99
+
100
+ # Get fiat value from response hash with crypto prices
101
+ # @example
102
+ # client.price(:btc)
103
+ #
104
+ # @param [Symbol] coin **Required**. Coin name as symbol.
105
+ # @return [Float]
106
+ #
107
+ def price(coin)
108
+ prices[coin.to_s.upcase]
109
+ end
110
+
111
+ # Check if request was successful.
112
+ #
113
+ def success?
114
+ return false if response.nil?
115
+
116
+ response[:success].is_a?(TrueClass)
117
+ end
118
+
119
+ private
120
+
121
+ def send_api_request(source)
122
+ # automatically add new sources to the client, but be careful with eval.
123
+ if List.sources.include? source
124
+ klass = check_source_name source
125
+
126
+ @response =
127
+ instance_eval "CTFC::API::#{klass}[ config[:fiat], config[:coins] ]"\
128
+ '# CTFC::API::Cryptocompare[fiat, coins]', __FILE__, __LINE__ - 1
129
+ else
130
+ message = 'Add source to extract data' if source.nil?
131
+ message = "#{source} not included in API list" if source
132
+ raise ArgumentError, message
133
+ end
134
+ end
135
+
136
+ # Check for underscore and capitalize each word.
137
+ #
138
+ def check_source_name(source)
139
+ if source.to_s.include? '_'
140
+ source.split('_').select(&:capitalize!).join
141
+ else
142
+ source.to_s.capitalize
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+
5
+ # Keep methods to export data as csv or json.
6
+ # JSON extract all data, while CSV only prices.
7
+ #
8
+ module Export
9
+ class << self
10
+ #
11
+ # Save crypto prices in csv table.
12
+ #
13
+ def to_csv(source, response = {})
14
+ table = "ctfc_#{response[:fiat]}_#{source}.csv"
15
+ coins = response[:coins]
16
+ data_row = price_array_from response
17
+ create_csv_headers(table, coins) unless File.exist?(table)
18
+ CSV.open(table, 'ab') { |column| column << data_row }
19
+ end
20
+
21
+ # Extract all data in json file.
22
+ #
23
+ def to_json(source, response = {})
24
+ table = "ctfc_#{response[:fiat]}_#{source}.json"
25
+ File.open(table, 'ab') do |append|
26
+ append.puts JSON.pretty_generate response
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def create_csv_headers(table, coins)
33
+ header_array = ['TIME']
34
+ coins.each { |coin| header_array << coin }
35
+ CSV.open(table, 'w') { |header| header << header_array }
36
+ end
37
+
38
+ def price_array_from(response = {})
39
+ price_array = [response[:time]]
40
+ response[:prices].each do |_coin, price|
41
+ price_array << price
42
+ end
43
+ price_array
44
+ end
45
+ end
46
+ end
data/lib/ctfc/version.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CTFC
4
- VERSION = '0.3.3'
4
+ # gem version
5
+ VERSION = '1.0.0.alpha'
5
6
  end
data/lib/ctfc.rb CHANGED
@@ -1,49 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'ctfc/base'
3
+ require_relative 'ctfc/client'
4
+ require_relative 'ctfc/version'
4
5
 
5
- ##
6
- # For easier job use Ctfc, instead of typing CTFC::Data.
7
- # You can define default coins with Ctfc::COINS=
8
- #
9
- # @note For instance methods look at CTFC::Data.
10
- #
11
- class Ctfc < CTFC::Data
12
- ##
13
- # @todo Allow Ctfc to use proxy and/or tor
14
- #
15
- def initialize(currency = :eur, opts = {})
16
- opts[:coins] ||= COINS
17
- super(currency, opts)
18
- end
19
-
20
- ##
21
- # @example Get EUR data for BTC, XMR, LTC, ETH, print but don't save output
22
- #
23
- # Ctfc.to :eur, save: false, coins: %w[BTC XMR LTC ETH]
24
- #
25
- # @param [Symbol] currency **Required**. Define fiat currency.
26
- # @param [Hash] opts **Optional**. Additional options hash.
27
- #
28
- # @option opts [Boolean] print **Optional**. Print terminal output.
29
- # @option opts [Boolean] save **Optional**. Save `.csv` output.
30
- # @option opts [Array] coins **Optional**. Define coins to scrap.
31
- #
32
- # @return [Hash] CTFC::Data#prices || CTFC::Data#response
33
- #
34
- def self.to(currency, opts = {})
35
- new(currency.to_sym, opts).get
36
- end
6
+ # Ctfc is shortcut for CTFC::Client.
7
+ # @see CTFC::Client
8
+ class Ctfc < CTFC::Client
37
9
  end
38
10
 
39
- ##
40
- # Same as Ctfc
41
- # @see Ctfc
42
- # @see CTFC::Data
11
+ # Shortcut to initialize new client,
12
+ # and get prices hash.
13
+ #
14
+ # @example Get EUR prices for coins:
15
+ # coins = %w[BTC XMR LTC ETH]
16
+ # Crypto.to :eur, coins, :cryptocompare, save: true
43
17
  #
44
- class Crypto < Ctfc
45
- def initialize(currency = :eur, opts = {})
46
- opts[:coins] ||= COINS
47
- super(currency, opts)
18
+ class Crypto
19
+ # @return [Hash]
20
+ # @see CTFC::Client
21
+ def self.to(*args)
22
+ CTFC::Client.new(*args).get
48
23
  end
49
24
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ctfc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 1.0.0.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - alx3dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-22 00:00:00.000000000 Z
11
+ date: 2022-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: colorize
14
+ name: kolorit
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.8.1
19
+ version: '0.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.8.1
26
+ version: '0.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: optimist
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,43 +58,47 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 2.2.9
61
+ version: '2.3'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 2.2.9
68
+ version: '2.3'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: pry
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.14.1
75
+ version: '0.14'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.14.1
82
+ version: '0.14'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rake
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 13.0.3
89
+ version: '13.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 13.0.3
97
- description: Convert any crypto to fiat currency and/or save in csv table.
96
+ version: '13.0'
97
+ description: |
98
+ == DEVELOPMENT VERSION==
99
+ Cryptocurrency data gathering gem. Get data from multiple APIs, print and
100
+ save output as you wish. Run script from terminal, or use in another app.
101
+ Class-template based, easy to extend to add more sources. MIT License.
98
102
  email:
99
103
  executables:
100
104
  - ctfc
@@ -103,12 +107,14 @@ extra_rdoc_files: []
103
107
  files:
104
108
  - LICENSE
105
109
  - README.md
106
- - bin/console
107
110
  - bin/ctfc
108
111
  - ctfc.gemspec
109
112
  - lib/ctfc.rb
110
- - lib/ctfc/base.rb
111
- - lib/ctfc/config.rb
113
+ - lib/ctfc/api.rb
114
+ - lib/ctfc/api/apitemplate.rb
115
+ - lib/ctfc/api/cryptocompare.rb
116
+ - lib/ctfc/client.rb
117
+ - lib/ctfc/export.rb
112
118
  - lib/ctfc/version.rb
113
119
  homepage: https://github.com/alx3dev/ctfc
114
120
  licenses:
@@ -117,7 +123,9 @@ metadata:
117
123
  homepage_uri: https://github.com/alx3dev/ctfc
118
124
  source_code_uri: https://github.com/alx3dev/ctfc
119
125
  bug_tracker_uri: https://github.com/alx3dev/ctfc/issues
120
- documentation_uri: https://rubydoc.info/gems/ctfc/0.3.3
126
+ changelog_uri: https://github.com/alx3dev/ctfc/CHANGELOG.md
127
+ documentation_uri: https://rubydoc.info/gems/ctfc/1.0.0.alpha
128
+ license_uri: https://github.com/alx3dev/ctfc/LICENSE
121
129
  rubygems_mfa_required: 'true'
122
130
  post_install_message:
123
131
  rdoc_options: []
@@ -125,17 +133,20 @@ require_paths:
125
133
  - lib
126
134
  required_ruby_version: !ruby/object:Gem::Requirement
127
135
  requirements:
128
- - - ">="
136
+ - - ">"
129
137
  - !ruby/object:Gem::Version
130
- version: 3.0.1
138
+ version: '2.7'
139
+ - - "<"
140
+ - !ruby/object:Gem::Version
141
+ version: '3.2'
131
142
  required_rubygems_version: !ruby/object:Gem::Requirement
132
143
  requirements:
133
- - - ">="
144
+ - - ">"
134
145
  - !ruby/object:Gem::Version
135
- version: '0'
146
+ version: 1.3.1
136
147
  requirements: []
137
- rubygems_version: 3.2.32
148
+ rubygems_version: 3.3.6
138
149
  signing_key:
139
150
  specification_version: 4
140
- summary: Crypto to Fiat currency data gathering
151
+ summary: Cryptocurrency data gathering gem. Scrap and save as CSV and/or JSON.
141
152
  test_files: []
data/bin/console DELETED
@@ -1,9 +0,0 @@
1
- #/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'pry'
5
- require 'bundler/setup'
6
-
7
- require_relative '../lib/ctfc'
8
-
9
- Pry.start
data/lib/ctfc/base.rb DELETED
@@ -1,196 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'config'
4
- require_relative 'version'
5
-
6
- require 'json'
7
- require 'csv'
8
- require 'colorize'
9
- require 'rest-client'
10
-
11
- module CTFC
12
- ##
13
- # Data class keep all the logic to send request, receive response,
14
- # and everything between. Class Ctfc extend CTFC::Data, for easier work.
15
- #
16
- # @note Instead of using CTFC::Data.new, recommended way is to call Ctfc.new
17
- #
18
- class Data
19
- include CONFIG
20
-
21
- attr_reader :response, :data, :url, :table, :count, :prices
22
- attr_accessor :fiat, :coins
23
-
24
- alias currency fiat
25
-
26
- ##
27
- # @example Initialization example
28
- #
29
- # @data = CTFC::Data.new :eur, save: true
30
- #
31
- # @param [Symbol] currency **Optional**. Define fiat currency.
32
- # @param [Hash] opts **Optional**. Additional options hash.
33
- #
34
- # @option opts [Boolean] print **Optional**. Print terminal output.
35
- # @option opts [Boolean] save **Optional**. Save `.csv` output.
36
- # @option opts [Array] coins **Optional**. Define coins to scrap.
37
- #
38
- # @return [Object] Data object to work with
39
- #
40
- def initialize(currency = :eur, opts = {})
41
- @fiat = currency.to_s.upcase
42
- @save = opts[:save].nil? ? true : opts[:save]
43
- @print = opts[:print].nil? ? true : opts[:print]
44
- @coins = opts[:coins].nil? ? COINS : Array(opts[:coins])
45
- end
46
-
47
- ##
48
- # @example Get fiat prices for previous config
49
- #
50
- # @data.get
51
- #
52
- # @example Get prices and change previous config "on-the-fly"
53
- #
54
- # @data.get :usd, save: false, coins: %w[BTC XMR ETH]
55
- #
56
- # @param [Symbol || String] currency **Optional**. Change fiat currency and execute request.
57
- # @param [Hash] opts **Optional**. Options hash to change config 'on-the-fly' - see #initialize.
58
- #
59
- def get(currency = nil, opts = {})
60
- @fiat = currency.to_s.upcase unless currency.nil?
61
- @coins = opts[:coins] unless opts[:coins].nil?
62
- @save = opts[:save] unless opts[:save].nil?
63
- @print = opts[:print] unless opts[:print].nil?
64
- @count = 0
65
- @table = "ctfc_#{@fiat}.csv".downcase
66
- do_rest_request
67
- end
68
-
69
- ##
70
- # Get fiat value from response hash with crypto prices
71
- #
72
- # @example
73
- #
74
- # @data.price(:btc)
75
- #
76
- # @param [Symbol || String] coin **Required**. Coin name as symbol or string.
77
- # @return [Float]
78
- #
79
- def price(coin)
80
- @prices[coin.to_s.upcase]
81
- end
82
-
83
- ##
84
- # Check if crypto prices will be saved in `.csv` table
85
- #
86
- # @return [true || false]
87
- #
88
- def save?
89
- @save == true
90
- end
91
-
92
- ##
93
- # Check if crypto prices will be printed in terminal
94
- #
95
- # @return [true || false]
96
- #
97
- def print?
98
- @print == true
99
- end
100
-
101
- ##
102
- # Change option to save '.csv' table with prices
103
- #
104
- # @return [true || false]
105
- #
106
- def save=(opt)
107
- @save = opt.is_a?(TrueClass)
108
- end
109
-
110
- ##
111
- # Change option to print prices in terminal
112
- #
113
- # @return [true || false]
114
- #
115
- def print=(opt)
116
- @print = opt.is_a?(TrueClass)
117
- end
118
-
119
- ##
120
- # Check if request was successful or not.
121
- #
122
- # @return [true || false]
123
- #
124
- def success?
125
- return false if @response.nil?
126
-
127
- @response.code == 200
128
- end
129
-
130
- private
131
-
132
- def do_rest_request
133
- prepare_uri
134
- process_data
135
- @prices
136
- rescue StandardError
137
- @count += 1
138
-
139
- if @count >= MAX_RETRY
140
- puts @response.to_s.split(',')
141
- else
142
- do_rest_request
143
- end
144
- end
145
-
146
- def process_data
147
- @response = RestClient.get @url
148
- @data = JSON.parse @response
149
-
150
- @data_array << Time.now.to_s
151
- @coins.each do |coin|
152
- value = @data['RAW'][coin.to_s.upcase][@fiat.to_s.upcase]['PRICE'].round(2)
153
- @prices[coin] = value
154
- @data_array << value
155
- end
156
-
157
- print_fiat_values
158
- save_csv_data
159
- end
160
-
161
- def prepare_uri
162
- @prices = {}
163
- @data_array = []
164
- coin_uri = String.new ''
165
- @coins.collect { |coin| coin_uri << "fsyms=#{coin}&" }
166
- @url = URL + "#{coin_uri}tsyms=#{@fiat}"
167
- end
168
-
169
- def print_fiat_values
170
- return unless print?
171
-
172
- 30.times { print '='.green }
173
- puts ''
174
- puts "#{'['.green}#{@fiat.to_s.upcase.yellow.bold}#{']'.green} conversion rate"
175
- 30.times { print '='.green }
176
- puts ''
177
- @prices.each do |name, value|
178
- print '['.yellow.bold + name.to_s.green.bold + ']'.yellow.bold
179
- puts ": #{value}".bold
180
- end
181
- end
182
-
183
- def save_csv_data
184
- return unless save?
185
-
186
- create_csv_headers unless File.exist?(@table)
187
- CSV.open(@table, 'ab') { |column| column << @data_array }
188
- end
189
-
190
- def create_csv_headers
191
- header_array = ['TIME']
192
- @coins.each { |coin| header_array << coin }
193
- CSV.open(@table, 'w') { |header| header << header_array }
194
- end
195
- end
196
- end
data/lib/ctfc/config.rb DELETED
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CTFC
4
- ##
5
- # Keep default configuration data, like coins to scrap, max number
6
- # of retries and cryptocompare API url.
7
- #
8
- module CONFIG
9
- # default coins to use
10
- COINS = %w[BTC LTC XMR ETH BCH ZEC].freeze
11
-
12
- # max number of retries if request fail
13
- MAX_RETRY = 3
14
-
15
- # Cryptocompare API - base url for requests
16
- URL = 'https://min-api.cryptocompare.com/data/pricemultifull?'
17
- end
18
- end