coincapper 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/LICENSE.txt +1 -1
- data/README.md +70 -8
- data/coincapper.gemspec +5 -5
- data/lib/coincapper.rb +154 -98
- data/lib/coincapper/version.rb +2 -2
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48cf58727f9ab2527e3172010e0b48d28d1c0591
|
4
|
+
data.tar.gz: 05a4c2a9a90b9fbb2ec76e2b9302f16f8cae56c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4515cdf093bdb3d2d34f47f7c4a9f82e989d12ea051643bb88e34bfc04aecd454e74c3d3a656881a8a7f2b966fc73655d9a7750567361529c3c386112d0c59e9
|
7
|
+
data.tar.gz: e956f186176adb955921aafde496ba271a66b85b9dfcb5ff42def6330ffbcc9469b4ba603c159ce70ebdcd8d64e84213c8821c159f20bc19d617f3fc418f24ee
|
data/.gitignore
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
|
3
3
|
# CoinCapper
|
4
4
|
|
5
|
-
|
5
|
+
An API wrapper to the V1 coinmarketcap.com public API with additional historic, symbol, and market functionality.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
9
|
Add this line to your application's Gemfile:
|
10
10
|
|
11
11
|
```ruby
|
12
|
-
gem 'coincapper',
|
12
|
+
gem 'coincapper', '~> 1.0'
|
13
13
|
```
|
14
14
|
|
15
15
|
And then execute:
|
@@ -30,7 +30,7 @@ Or install it yourself as:
|
|
30
30
|
CoinCapper.coins(limit: 0, rank: nil, currency: nil)
|
31
31
|
```
|
32
32
|
|
33
|
-
#### Coin by
|
33
|
+
#### Coin by CoinMarketCap ID
|
34
34
|
|
35
35
|
```ruby
|
36
36
|
CoinCapper.coin('litecoin', currency: nil)
|
@@ -48,18 +48,80 @@ CoinCapper.global(currency: nil)
|
|
48
48
|
|
49
49
|
```ruby
|
50
50
|
CoinCapper.coin_by_symbol('FUN')
|
51
|
+
|
52
|
+
=> {:id=>"funfair",
|
53
|
+
:name=>"FunFair",
|
54
|
+
:symbol=>"FUN",
|
55
|
+
:rank=>"84",
|
56
|
+
:price_usd=>"0.0382094",
|
57
|
+
:price_btc=>"0.00000557",
|
58
|
+
:"24h_volume_usd"=>"5375680.0",
|
59
|
+
:market_cap_usd=>"172083246.0",
|
60
|
+
:available_supply=>"4503688789.0",
|
61
|
+
:total_supply=>"10999873621.0",
|
62
|
+
:max_supply=>nil,
|
63
|
+
:percent_change_1h=>"-6.89",
|
64
|
+
:percent_change_24h=>"-24.77",
|
65
|
+
:percent_change_7d=>"-59.6",
|
66
|
+
:last_updated=>"1517873357"}
|
51
67
|
```
|
52
68
|
|
53
|
-
####
|
69
|
+
#### Available markets by coin id or symbol
|
54
70
|
|
55
71
|
```ruby
|
56
72
|
CoinCapper.coin_markets(id: 'iota', symbol: nil)
|
73
|
+
|
74
|
+
=> [{:source=>"Bitfinex", :pair=>"MIOTA/USD", :volume_usd=>33835200.0, :price_usd=>1.41, :volume_percentage=>50.21, :last_updated=>"Recently"},
|
75
|
+
{:source=>"Binance", :pair=>"IOTA/BTC", :volume_usd=>7733790.0, :price_usd=>1.41, :volume_percentage=>11.48, :last_updated=>"Recently"}]
|
76
|
+
```
|
77
|
+
|
78
|
+
#### Historical prices by id, start, end date
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
CoinCapper.historical_price('request-network', '2018-01-01', '2018-01-02')
|
82
|
+
|
83
|
+
=> [{:date=>"2018-01-02", :open=>0.8126, :high=>0.881387, :low=>0.650608, :close=>0.783648, :average=>0.7659975},
|
84
|
+
{:date=>"2018-01-01", :open=>0.606538, :high=>0.888908, :low=>0.528808, :close=>0.820232, :average=>0.708858}]
|
57
85
|
```
|
58
86
|
|
59
|
-
####
|
87
|
+
#### All Cryptocurrencies by type (coins, tokens)
|
60
88
|
|
61
89
|
```ruby
|
62
|
-
|
90
|
+
# coins
|
91
|
+
CoinCapper.all('coins')
|
92
|
+
|
93
|
+
=> [{:id=>"bitcoin",
|
94
|
+
:rank=>1,
|
95
|
+
:name=>"Bitcoin",
|
96
|
+
:symbol=>"BTC",
|
97
|
+
:market_cap_usd=>116671271686.0,
|
98
|
+
:market_cap_btc=>16848275.0,
|
99
|
+
:price_usd=>6924.82,
|
100
|
+
:price_btc=>1.0,
|
101
|
+
:circulating_supply=>16848275.0,
|
102
|
+
:volume_usd_24h=>9116750000.0,
|
103
|
+
:volume_btc_24h=>1309170.0,
|
104
|
+
:percent_change_1h=>-4.59,
|
105
|
+
:percent_change_24h=>-16.75,
|
106
|
+
:percent_change_7d=>-38.38}]
|
107
|
+
|
108
|
+
# tokens
|
109
|
+
CoinCapper.all('tokens')
|
110
|
+
|
111
|
+
=> [{:id=>"eos",
|
112
|
+
:rank=>1,
|
113
|
+
:name=>"EOS",
|
114
|
+
:platform=>"Ethereum",
|
115
|
+
:market_cap_usd=>4598392073.93,
|
116
|
+
:market_cap_btc=>663307.647514,
|
117
|
+
:price_usd=>7.07817,
|
118
|
+
:price_btc=>0.00102101,
|
119
|
+
:circulating_supply=>649658326.083,
|
120
|
+
:volume_usd_24h=>630722000.0,
|
121
|
+
:volume_btc_24h=>90980.3,
|
122
|
+
:percent_change_1h=>-6.02,
|
123
|
+
:percent_change_24h=>-18.88,
|
124
|
+
:percent_change_7d=>-49.0}]
|
63
125
|
```
|
64
126
|
|
65
127
|
## Development
|
@@ -70,7 +132,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
70
132
|
|
71
133
|
## Contributing
|
72
134
|
|
73
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/kurt-smith/
|
135
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/kurt-smith/coincapper. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
74
136
|
|
75
137
|
## License
|
76
138
|
|
@@ -78,4 +140,4 @@ The gem is available as open source under the terms of the [MIT License](http://
|
|
78
140
|
|
79
141
|
## Code of Conduct
|
80
142
|
|
81
|
-
Everyone interacting in the CoinCapper project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/kurt-smith/
|
143
|
+
Everyone interacting in the CoinCapper project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/kurt-smith/coincapper/blob/master/CODE_OF_CONDUCT.md).
|
data/coincapper.gemspec
CHANGED
@@ -9,9 +9,9 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.version = CoinCapper::VERSION
|
10
10
|
spec.authors = ['Kurt Smith']
|
11
11
|
spec.email = ['zippydev@protonmail.com']
|
12
|
-
|
13
|
-
spec.
|
14
|
-
|
12
|
+
spec.summary = 'Coinmarketcap V1 API wrapper'
|
13
|
+
spec.description = 'coinmarketcap.com V1 API wrapper including additional historical prices, coin market pairs, '\
|
14
|
+
'and currencies by type (coins/tokens) parsed from Coin Market Cap.'
|
15
15
|
spec.homepage = 'https://github.com/kurt-smith/coincapper'
|
16
16
|
spec.license = 'MIT'
|
17
17
|
|
@@ -38,7 +38,7 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.add_development_dependency 'pry', '~> 0.11'
|
39
39
|
spec.add_development_dependency 'rake', '~> 10.0'
|
40
40
|
spec.add_development_dependency 'rspec', '~> 3.7'
|
41
|
-
spec.add_development_dependency 'rubocop'
|
42
|
-
spec.add_development_dependency 'simplecov'
|
41
|
+
spec.add_development_dependency 'rubocop', '>= 0.52'
|
42
|
+
spec.add_development_dependency 'simplecov', '>= 0.14'
|
43
43
|
spec.add_development_dependency 'webmock', '~> 3.2'
|
44
44
|
end
|
data/lib/coincapper.rb
CHANGED
@@ -6,120 +6,176 @@ require 'coincapper/version'
|
|
6
6
|
require 'http'
|
7
7
|
require 'nokogiri'
|
8
8
|
|
9
|
-
|
9
|
+
class CoinCapper
|
10
10
|
API_URL = 'https://api.coinmarketcap.com/v1'.freeze
|
11
11
|
BASE_URL = 'https://coinmarketcap.com'.freeze
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
13
|
+
class << self
|
14
|
+
# @param rank [Integer] Coins market cap rank greater than or equal
|
15
|
+
# @param limit [Integer] Maximum limit set. Defaults to 0 to return all results
|
16
|
+
# @param currency [String] Country currency code to convert price
|
17
|
+
# @return [Array<Hash>]
|
18
|
+
# @see https://coinmarketcap.com/api/
|
19
|
+
def coins(limit: 0, rank: nil, currency: nil)
|
20
|
+
params = {
|
21
|
+
limit: limit,
|
22
|
+
start: rank,
|
23
|
+
convert: currency
|
24
|
+
}.compact.to_param
|
25
|
+
|
26
|
+
url = "#{API_URL}/ticker/"
|
27
|
+
url << "?#{params}" if params.present?
|
28
|
+
|
29
|
+
response = HTTP.get(url)
|
30
|
+
JSON.parse(response.body.to_s, symbolize_names: true)
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
# @param id [Integer] Coinmarketcap coin id
|
34
|
+
# @param currency [String] Country currency code to convert price
|
35
|
+
# @return [Hash]
|
36
|
+
def coin(id, currency: nil)
|
37
|
+
params = {
|
38
|
+
convert: currency
|
39
|
+
}.compact.to_param
|
39
40
|
|
40
|
-
|
41
|
-
|
41
|
+
url = "#{API_URL}/ticker/#{id}/"
|
42
|
+
url << "?#{params}" if params.present?
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
response = HTTP.get(url)
|
45
|
+
json = JSON.parse(response.body.to_s, symbolize_names: true)
|
46
|
+
json.is_a?(Array) ? json.first : json
|
47
|
+
end
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
49
|
+
# @param symbol [String] Coin symbol
|
50
|
+
# @return [Hash]
|
51
|
+
def coin_by_symbol(symbol)
|
52
|
+
response = HTTP.get("#{API_URL}/ticker/?limit=0")
|
53
|
+
json = JSON.parse(response.body.to_s, symbolize_names: true)
|
54
|
+
json.find { |x| x[:symbol].strip.casecmp(symbol.strip.upcase).zero? }
|
55
|
+
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
57
|
+
# @param id [String] Coin market cap id
|
58
|
+
# @param symbol [String] Coin symbol
|
59
|
+
# @return [Array<Hash>]
|
60
|
+
def coin_markets(id: nil, symbol: nil)
|
61
|
+
raise ArgumentError.new('id or symbol is required') if id.blank? && symbol.blank?
|
62
|
+
|
63
|
+
coin_id = symbol.present? ? coin_by_symbol(symbol)[:id] : id
|
64
|
+
response = HTTP.get("#{BASE_URL}/currencies/#{coin_id}/\#markets")
|
65
|
+
html = Nokogiri::HTML(response.body.to_s)
|
66
|
+
rows = html.css('table#markets-table tbody tr')
|
67
|
+
return { error: 'invalid id' } if rows.blank?
|
68
|
+
|
69
|
+
markets = rows.each_with_object([]) do |row, arr|
|
70
|
+
td = row.css('td')
|
71
|
+
arr << {
|
72
|
+
source: td[1].text.strip,
|
73
|
+
pair: td[2].text.strip,
|
74
|
+
volume_usd: td[3].text.strip[/\$(.+)/, 1].delete(',').to_f,
|
75
|
+
price_usd: td[4].text.strip[/\$(.+)/, 1].delete(',').to_f,
|
76
|
+
volume_percentage: td[5].text.to_f,
|
77
|
+
last_updated: td[6].text.strip
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
markets
|
77
82
|
end
|
78
83
|
|
79
|
-
|
80
|
-
|
84
|
+
# @param currency [String] Country currency code to convert price
|
85
|
+
# @return [Hash]
|
86
|
+
def global(currency: nil)
|
87
|
+
params = {
|
88
|
+
convert: currency
|
89
|
+
}.compact.to_param
|
81
90
|
|
82
|
-
|
83
|
-
|
84
|
-
def self.global(currency: nil)
|
85
|
-
params = {
|
86
|
-
convert: currency
|
87
|
-
}.compact.to_param
|
91
|
+
url = "#{API_URL}/global/"
|
92
|
+
url << "?#{params}" if params.present?
|
88
93
|
|
89
|
-
|
90
|
-
|
94
|
+
response = HTTP.get(url)
|
95
|
+
JSON.parse(response.body.to_s, symbolize_names: true)
|
96
|
+
end
|
91
97
|
|
92
|
-
|
93
|
-
|
94
|
-
|
98
|
+
# @param id [String] Coinmarketcap coin id
|
99
|
+
# @param start_date [String] Start date (YYYY-MM-DD)
|
100
|
+
# @param end_date [String] End date (YYYY-MM-DD)
|
101
|
+
# @return [Array<Hash>]
|
102
|
+
def historical_price(id, start_date, end_date)
|
103
|
+
sd = parse_date(start_date, format: '%Y%m%d')
|
104
|
+
ed = parse_date(end_date, format: '%Y%m%d')
|
105
|
+
return { error: 'invalid date format' } if sd.blank? || ed.blank?
|
106
|
+
|
107
|
+
url = "#{BASE_URL}/currencies/#{id}/historical-data/?start=#{sd}&end=#{ed}"
|
108
|
+
response = HTTP.get(url)
|
109
|
+
html = Nokogiri::HTML(response.body.to_s)
|
110
|
+
rows = html.css('#historical-data table tbody tr')
|
111
|
+
return { error: 'invalid id' } if rows.blank?
|
112
|
+
|
113
|
+
prices = rows.each_with_object([]) do |row, arr|
|
114
|
+
td = row.css('td')
|
115
|
+
daily = {
|
116
|
+
date: parse_date(td[0].text, format: '%F'),
|
117
|
+
open: td[1].text.to_f,
|
118
|
+
high: td[2].text.to_f,
|
119
|
+
low: td[3].text.to_f,
|
120
|
+
close: td[4].text.to_f
|
121
|
+
}
|
122
|
+
|
123
|
+
daily[:average] = ((daily[:high] + daily[:low]).to_d / 2).to_f
|
124
|
+
arr << daily
|
125
|
+
end
|
126
|
+
|
127
|
+
prices
|
128
|
+
end
|
95
129
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
130
|
+
# Returns list of cryptocurrencies by type (coins, tokens)
|
131
|
+
# @param type [String] Cryptocurrency type. i.e. 'coins' or 'tokens'
|
132
|
+
# @return [Array<Hash>] List of all coins (or tokens)
|
133
|
+
def all(type)
|
134
|
+
return { error: 'invalid type' } unless /coins|tokens/ =~ type
|
135
|
+
|
136
|
+
url = "#{BASE_URL}/#{type}/views/all/"
|
137
|
+
response = HTTP.get(url)
|
138
|
+
html = Nokogiri::HTML(response.body.to_s)
|
139
|
+
table = html.css('table#currencies-all, table#assets-all')
|
140
|
+
rows = table.css('tbody tr')
|
141
|
+
|
142
|
+
cryptos = rows.each_with_object([]) do |row, arr|
|
143
|
+
td = row.css('td')
|
144
|
+
arr << {
|
145
|
+
id: row&.attribute('id')&.text[/id-(.+)/, 1],
|
146
|
+
rank: td[0].text.to_i,
|
147
|
+
name: td[1].css('a.currency-name-container').text.strip,
|
148
|
+
symbol: type.eql?('coins') ? td[2].text : nil,
|
149
|
+
platform: type.eql?('tokens') ? td[2].text : nil,
|
150
|
+
market_cap_usd: td[3]&.attribute('data-usd')&.text.to_f,
|
151
|
+
market_cap_btc: td[3]&.attribute('data-btc')&.text.to_f,
|
152
|
+
price_usd: td[4].css('a.price')&.attribute('data-usd')&.text.to_f,
|
153
|
+
price_btc: td[4].css('a.price')&.attribute('data-btc')&.text.to_f,
|
154
|
+
circulating_supply: td[5].css('a, span')&.attribute('data-supply')&.text.to_f,
|
155
|
+
volume_usd_24h: td[6].css('a')&.attribute('data-usd')&.text.to_f,
|
156
|
+
volume_btc_24h: td[6].css('a')&.attribute('data-btc')&.text.to_f,
|
157
|
+
percent_change_1h: td[7]&.attribute('data-usd')&.text.to_f,
|
158
|
+
percent_change_24h: td[8]&.attribute('data-usd')&.text.to_f,
|
159
|
+
percent_change_7d: td[9]&.attribute('data-usd')&.text.to_f
|
160
|
+
}.compact
|
161
|
+
end
|
162
|
+
|
163
|
+
cryptos
|
164
|
+
rescue StandardError => e
|
165
|
+
{
|
166
|
+
message: 'An unknown error occurred. Please submit a GitHub issue if problem continues.',
|
167
|
+
error: e.message
|
117
168
|
}
|
118
|
-
|
119
|
-
daily[:average] = ((daily[:high] + daily[:low]).to_d / 2).to_f
|
120
|
-
arr << daily
|
121
169
|
end
|
122
170
|
|
123
|
-
|
171
|
+
private
|
172
|
+
|
173
|
+
def parse_date(date, format: nil)
|
174
|
+
d = Date.parse(date)
|
175
|
+
return d if format.blank?
|
176
|
+
d.strftime(format)
|
177
|
+
rescue StandardError
|
178
|
+
nil
|
179
|
+
end
|
124
180
|
end
|
125
181
|
end
|
data/lib/coincapper/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coincapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kurt Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -114,28 +114,28 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
117
|
+
version: '0.52'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
124
|
+
version: '0.52'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: simplecov
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
131
|
+
version: '0.14'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
138
|
+
version: '0.14'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: webmock
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,8 +150,9 @@ dependencies:
|
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '3.2'
|
153
|
-
description: coinmarketcap.com V1 API wrapper including additional historical prices
|
154
|
-
|
153
|
+
description: coinmarketcap.com V1 API wrapper including additional historical prices,
|
154
|
+
coin market pairs, and currencies by type (coins/tokens) parsed from Coin Market
|
155
|
+
Cap.
|
155
156
|
email:
|
156
157
|
- zippydev@protonmail.com
|
157
158
|
executables: []
|
@@ -196,5 +197,5 @@ rubyforge_project:
|
|
196
197
|
rubygems_version: 2.6.11
|
197
198
|
signing_key:
|
198
199
|
specification_version: 4
|
199
|
-
summary:
|
200
|
+
summary: Coinmarketcap V1 API wrapper
|
200
201
|
test_files: []
|