cointools 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +52 -5
- data/bin/coinmcap +96 -0
- data/bin/cryptowatch +1 -1
- data/lib/cointools/coinmarketcap.rb +135 -0
- data/lib/cointools/cryptowatch.rb +1 -1
- data/lib/cointools/version.rb +1 -1
- data/lib/cointools.rb +1 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae9c00c6df51d228fb5d401f849d963ff2c05dfb
|
4
|
+
data.tar.gz: cd3ed48eb9317db5d26085f8fc0059f9788a9759
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcb355f0ce41f2d570425c974e91fc20510073d214c574ace8009b37a0d4fe2fc07f4fa6360e5081cfa9a96a56e76eac1ee9778e08bc24e6354bc5a31e716d38
|
7
|
+
data.tar.gz: 2ea61e0a5f07649ea6592b0a003058de5d4c2bedbf2f8d7d37f3aba4bc7ba040479f9747a18e52bc9f36c40c087b951c490b29d3d90af838bd97616416c58499
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Cointools
|
2
2
|
|
3
|
-
This is a collection of Ruby scripts and library classes that let you check cryptocurrency prices on various services
|
3
|
+
This is a collection of Ruby scripts and library classes that let you check cryptocurrency prices on various services.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -16,9 +16,7 @@ To use the code as a library, add it to your Gemfile:
|
|
16
16
|
gem 'cointools'
|
17
17
|
```
|
18
18
|
|
19
|
-
##
|
20
|
-
|
21
|
-
### [Cryptowatch](https://cryptowat.ch)
|
19
|
+
## [Cryptowatch](https://cryptowat.ch)
|
22
20
|
|
23
21
|
To check past price of a given coin on a chosen exchange, pass the exchange and market name and a properly formatted timestamp:
|
24
22
|
|
@@ -42,7 +40,7 @@ cryptowatch --list-markets bithumb
|
|
42
40
|
In code:
|
43
41
|
|
44
42
|
```ruby
|
45
|
-
require 'cointools'
|
43
|
+
require 'cointools' # or 'cointools/cryptowatch'
|
46
44
|
cryptowatch = CoinTools::Cryptowatch.new
|
47
45
|
|
48
46
|
exchange = cryptowatch.exchanges.first
|
@@ -60,6 +58,55 @@ puts "#{market} today: #{result.price}"
|
|
60
58
|
The result object contains the requested price and (for historical prices) the actual timestamp of the found price, which might slightly differ from the timestamp passed in the argument (the earlier the date, the less precise the result).
|
61
59
|
|
62
60
|
|
61
|
+
## [CoinMarketCap](https://coinmarketcap.com)
|
62
|
+
|
63
|
+
CoinMarketCap's API only returns current coin prices. To look up a coin's price, you need to pass its name as used on CoinMarketCap:
|
64
|
+
|
65
|
+
```
|
66
|
+
coinmcap power-ledger
|
67
|
+
```
|
68
|
+
|
69
|
+
Alternatively, you can pass the cryptocurrency's symbol using the `-s` or `--symbol` parameter:
|
70
|
+
|
71
|
+
```
|
72
|
+
coinmcap -s powr
|
73
|
+
```
|
74
|
+
|
75
|
+
However, this operation needs to download a complete ticker for all currencies and scan through the list, so it's recommended to use the name as in the example above.
|
76
|
+
|
77
|
+
You can also use the `-b` or `--btc-price` flag to request a price in BTC instead of USD:
|
78
|
+
|
79
|
+
```
|
80
|
+
coinmcap power-ledger -b
|
81
|
+
```
|
82
|
+
|
83
|
+
Or you can request the price in one of the ~30 other supported fiat currencies with `-f` or `--fiat-currency`:
|
84
|
+
|
85
|
+
```
|
86
|
+
coinmcap request-network -fEUR
|
87
|
+
```
|
88
|
+
|
89
|
+
You can print a list of supported fiat currencies with `coinmcap --list-fiat-currencies`.
|
90
|
+
|
91
|
+
Same things in code:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
require 'cointools' # or 'cointools/coinmarketcap'
|
95
|
+
cmc = CoinTools::CoinMarketCap.new
|
96
|
+
|
97
|
+
p CoinTools::CoinMarketCap::FIAT_CURRENCIES
|
98
|
+
|
99
|
+
ltc = cryptowatch.get_price('litecoin')
|
100
|
+
puts "LTC: #{ltc.usd_price} USD / #{ltc.btc_price} BTC"
|
101
|
+
|
102
|
+
xmr = cryptowatch.get_price_by_symbol('xmr')
|
103
|
+
puts "XMR: #{xmr.usd_price} USD / #{xmr.btc_price} BTC"
|
104
|
+
|
105
|
+
eth = cryptowatch.get_price('ethereum', convert_to: 'EUR')
|
106
|
+
puts "ETH: #{eth.converted_price} EUR"
|
107
|
+
```
|
108
|
+
|
109
|
+
|
63
110
|
## Credits & contributing
|
64
111
|
|
65
112
|
Copyright © 2018 [Kuba Suder](https://mackuba.eu). Licensed under [Very Simple Public License](https://github.com/mackuba/cointools/blob/master/VSPL-LICENSE.txt), my custom license that's basically a simplified version of the MIT license that fits in 3 lines.
|
data/bin/coinmcap
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'cointools'
|
5
|
+
|
6
|
+
require 'optparse'
|
7
|
+
require 'time'
|
8
|
+
|
9
|
+
def print_help
|
10
|
+
puts "Usage: #{$PROGRAM_NAME} <coin_name> [-b/--btc-price] [-fXXX/--fiat-currency XXX] [-v/--verbose]"
|
11
|
+
puts " e.g.: #{$PROGRAM_NAME} litecoin"
|
12
|
+
puts
|
13
|
+
puts "* To look up the currency by symbol instead of name (slower, downloads more data):"
|
14
|
+
puts " #{$PROGRAM_NAME} -s/--symbol <symbol> [-b/--btc-price] [-fXXX/--fiat-currency XXX] [-v/--verbose]"
|
15
|
+
puts " e.g.: #{$PROGRAM_NAME} -s LTC"
|
16
|
+
puts
|
17
|
+
puts "* To list supported fiat currencies:"
|
18
|
+
puts " #{$PROGRAM_NAME} --list-fiat-currences"
|
19
|
+
puts
|
20
|
+
puts "* -b / --btc-price: returns the coin's price in BTC instead of USD"
|
21
|
+
puts "* -fEUR / --fiat-currency EUR: returns the price in a given fiat currency instead of USD"
|
22
|
+
end
|
23
|
+
|
24
|
+
verbose = false
|
25
|
+
btc_price = false
|
26
|
+
fiat_currency = nil
|
27
|
+
symbol = nil
|
28
|
+
|
29
|
+
OptionParser.new do |opts|
|
30
|
+
opts.on('-v', '--verbose') { verbose = true }
|
31
|
+
opts.on('-b', '--btc-price') { btc_price = true }
|
32
|
+
opts.on('-fXXX', '--fiat-currency XXX') { |f| fiat_currency = f }
|
33
|
+
|
34
|
+
opts.on('--list-fiat-currencies') do
|
35
|
+
puts CoinTools::CoinMarketCap::FIAT_CURRENCIES
|
36
|
+
exit 0
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on('-h', '--help') do
|
40
|
+
print_help
|
41
|
+
exit 0
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on('-sSYMBOL', '--symbol SYMBOL') { |s| symbol = s }
|
45
|
+
|
46
|
+
opts.parse!
|
47
|
+
end
|
48
|
+
|
49
|
+
unless symbol
|
50
|
+
if ARGV.length != 1
|
51
|
+
print_help
|
52
|
+
exit 1
|
53
|
+
end
|
54
|
+
|
55
|
+
coin_name = ARGV[0].downcase
|
56
|
+
end
|
57
|
+
|
58
|
+
if fiat_currency && btc_price
|
59
|
+
puts "#{$PROGRAM_NAME}: --btc-price and --fiat-currency options cannot be used together"
|
60
|
+
exit 2
|
61
|
+
end
|
62
|
+
|
63
|
+
begin
|
64
|
+
if symbol
|
65
|
+
result = CoinTools::CoinMarketCap.new.get_price_by_symbol(symbol, convert_to: fiat_currency)
|
66
|
+
else
|
67
|
+
result = CoinTools::CoinMarketCap.new.get_price(coin_name, convert_to: fiat_currency)
|
68
|
+
end
|
69
|
+
|
70
|
+
if btc_price
|
71
|
+
price = result.btc_price
|
72
|
+
unit = 'BTC'
|
73
|
+
elsif fiat_currency
|
74
|
+
price = result.converted_price
|
75
|
+
unit = fiat_currency.upcase
|
76
|
+
else
|
77
|
+
price = result.usd_price
|
78
|
+
unit = 'USD'
|
79
|
+
end
|
80
|
+
|
81
|
+
if verbose
|
82
|
+
puts "#{symbol&.upcase || coin_name} @ #{result.time || Time.now} ==> #{price} #{unit}"
|
83
|
+
puts
|
84
|
+
else
|
85
|
+
puts price
|
86
|
+
end
|
87
|
+
rescue CoinTools::CoinMarketCap::InvalidResponseException => e
|
88
|
+
$stderr.puts "Error: Incorrect coin name: #{coin_name} (#{e})"
|
89
|
+
exit 3
|
90
|
+
rescue CoinTools::CoinMarketCap::NoDataException => e
|
91
|
+
$stderr.puts "Error: #{e}"
|
92
|
+
exit 4
|
93
|
+
rescue CoinTools::CoinMarketCap::InvalidFiatCurrencyException => e
|
94
|
+
$stderr.puts "Error: Unsupported fiat currency: #{fiat_currency}"
|
95
|
+
exit 5
|
96
|
+
end
|
data/bin/cryptowatch
CHANGED
@@ -66,7 +66,7 @@ rescue CoinTools::Cryptowatch::InvalidDateException => e
|
|
66
66
|
$stderr.puts "Error: #{e}"
|
67
67
|
exit 2
|
68
68
|
rescue CoinTools::Cryptowatch::BadRequestException => e
|
69
|
-
$stderr.puts "Error: Incorrect exchange or market name
|
69
|
+
$stderr.puts "Error: Incorrect exchange or market name (#{e})"
|
70
70
|
exit 3
|
71
71
|
rescue CoinTools::Cryptowatch::NoDataException => e
|
72
72
|
$stderr.puts "Error: #{e}: data not ready yet"
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require_relative 'version'
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'net/http'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
module CoinTools
|
8
|
+
class CoinMarketCap
|
9
|
+
BASE_URL = "https://api.coinmarketcap.com"
|
10
|
+
USER_AGENT = "cointools/#{CoinTools::VERSION}"
|
11
|
+
|
12
|
+
FIAT_CURRENCIES = [
|
13
|
+
'AUD', 'BRL', 'CAD', 'CHF', 'CLP', 'CNY', 'CZK', 'DKK', 'EUR', 'GBP',
|
14
|
+
'HKD', 'HUF', 'IDR', 'ILS', 'INR', 'JPY', 'KRW', 'MXN', 'MYR', 'NOK',
|
15
|
+
'NZD', 'PHP', 'PKR', 'PLN', 'RUB', 'SEK', 'SGD', 'THB', 'TRY', 'TWD',
|
16
|
+
'ZAR'
|
17
|
+
]
|
18
|
+
|
19
|
+
class DataPoint
|
20
|
+
attr_reader :time, :usd_price, :btc_price, :converted_price
|
21
|
+
|
22
|
+
def initialize(time, usd_price, btc_price, converted_price = nil)
|
23
|
+
@time = time
|
24
|
+
@usd_price = usd_price
|
25
|
+
@btc_price = btc_price
|
26
|
+
@converted_price = converted_price
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class InvalidResponseException < StandardError
|
31
|
+
attr_reader :response
|
32
|
+
|
33
|
+
def initialize(response)
|
34
|
+
super("#{response.code} #{response.message}")
|
35
|
+
@response = response
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class BadRequestException < InvalidResponseException
|
40
|
+
end
|
41
|
+
|
42
|
+
class NoDataException < StandardError
|
43
|
+
end
|
44
|
+
|
45
|
+
class InvalidFiatCurrencyException < StandardError
|
46
|
+
end
|
47
|
+
|
48
|
+
class InvalidDateException < StandardError
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_price(coin_name, convert_to: nil)
|
52
|
+
url = URI("#{BASE_URL}/v1/ticker/#{coin_name}/")
|
53
|
+
|
54
|
+
if convert_to
|
55
|
+
validate_fiat_currency(convert_to)
|
56
|
+
url += "?convert=#{convert_to}"
|
57
|
+
end
|
58
|
+
|
59
|
+
response = make_request(url)
|
60
|
+
|
61
|
+
case response
|
62
|
+
when Net::HTTPSuccess
|
63
|
+
json = JSON.load(response.body)
|
64
|
+
record = json[0]
|
65
|
+
|
66
|
+
usd_price = record['price_usd']&.to_f
|
67
|
+
btc_price = record['price_btc']&.to_f
|
68
|
+
timestamp = Time.at(record['last_updated'].to_i)
|
69
|
+
|
70
|
+
if convert_to
|
71
|
+
converted_price = record["price_#{convert_to.downcase}"]&.to_f
|
72
|
+
raise NoDataException.new('Conversion to chosen fiat currency failed') if converted_price.nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
return DataPoint.new(timestamp, usd_price, btc_price, converted_price)
|
76
|
+
when Net::HTTPBadRequest
|
77
|
+
raise BadRequestException.new(response)
|
78
|
+
else
|
79
|
+
raise InvalidResponseException.new(response)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_price_by_symbol(coin_symbol, convert_to: nil)
|
84
|
+
url = URI("#{BASE_URL}/v1/ticker/?limit=0")
|
85
|
+
symbol = coin_symbol.downcase
|
86
|
+
|
87
|
+
if convert_to
|
88
|
+
validate_fiat_currency(convert_to)
|
89
|
+
url += "&convert=#{convert_to}"
|
90
|
+
end
|
91
|
+
|
92
|
+
response = make_request(url)
|
93
|
+
|
94
|
+
case response
|
95
|
+
when Net::HTTPSuccess
|
96
|
+
json = JSON.load(response.body)
|
97
|
+
record = json.detect { |r| r['symbol'].downcase == symbol }
|
98
|
+
raise NoDataException.new('No coin found with given symbol') if record.nil?
|
99
|
+
|
100
|
+
usd_price = record['price_usd']&.to_f
|
101
|
+
btc_price = record['price_btc']&.to_f
|
102
|
+
timestamp = Time.at(record['last_updated'].to_i)
|
103
|
+
|
104
|
+
if convert_to
|
105
|
+
converted_price = record["price_#{convert_to.downcase}"]&.to_f
|
106
|
+
raise NoDataException.new('Conversion to chosen fiat currency failed') if converted_price.nil?
|
107
|
+
end
|
108
|
+
|
109
|
+
return DataPoint.new(timestamp, usd_price, btc_price, converted_price)
|
110
|
+
when Net::HTTPBadRequest
|
111
|
+
raise BadRequestException.new(response)
|
112
|
+
else
|
113
|
+
raise Exception.new(response)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def validate_fiat_currency(fiat_currency)
|
121
|
+
unless FIAT_CURRENCIES.include?(fiat_currency.upcase)
|
122
|
+
raise InvalidFiatCurrencyException
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def make_request(url)
|
127
|
+
Net::HTTP.start(url.host, url.port, use_ssl: true) do |http|
|
128
|
+
request = Net::HTTP::Get.new(url)
|
129
|
+
request['User-Agent'] = USER_AGENT
|
130
|
+
|
131
|
+
http.request(request)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/lib/cointools/version.rb
CHANGED
data/lib/cointools.rb
CHANGED
metadata
CHANGED
@@ -1,27 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cointools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kuba Suder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
15
15
|
- jakub.suder@gmail.com
|
16
16
|
executables:
|
17
17
|
- cryptowatch
|
18
|
+
- coinmcap
|
18
19
|
extensions: []
|
19
20
|
extra_rdoc_files: []
|
20
21
|
files:
|
22
|
+
- CHANGELOG.md
|
21
23
|
- README.md
|
22
24
|
- VSPL-LICENSE.txt
|
25
|
+
- bin/coinmcap
|
23
26
|
- bin/cryptowatch
|
24
27
|
- lib/cointools.rb
|
28
|
+
- lib/cointools/coinmarketcap.rb
|
25
29
|
- lib/cointools/cryptowatch.rb
|
26
30
|
- lib/cointools/version.rb
|
27
31
|
homepage: https://github.com/mackuba/cointools
|
@@ -44,7 +48,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
44
48
|
version: '0'
|
45
49
|
requirements: []
|
46
50
|
rubyforge_project:
|
47
|
-
rubygems_version: 2.5.
|
51
|
+
rubygems_version: 2.5.2
|
48
52
|
signing_key:
|
49
53
|
specification_version: 4
|
50
54
|
summary: A collection of scripts for checking cryptocurrency prices.
|