coinmarketcap.rb 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9418640a33531147099044276f4ae89f219e52f97def35df2581d85eb61f59b7
4
+ data.tar.gz: 565de31e863b431b9d772e7ded94cfffd0d607fa5829018600947b7cf7837ca1
5
+ SHA512:
6
+ metadata.gz: 5315e3dd994ef654670772cdff4efecc7d8a992489720497b17f18223fdb7008de1127315d1f4c405d0fd656b7bd08aa593ba2a56029e98e463180a81c5e4758
7
+ data.tar.gz: 4e575c130f2aa09d041a0ae5183a02a617958064841d87016e028960179df70af07455859d6c1f8840e8b5960ec4f32df41fccc48e804d016daf7b391817c7aa
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'http.rb'
4
+
5
+ group :development, :test do
6
+ gem 'minitest'
7
+ gem 'minitest-spec-context'
8
+ gem 'vcr'
9
+ end
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # coinmarketcap.rb
2
+
3
+ ## Description
4
+
5
+ Access the coinmarketcap.com API with Ruby.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+ ```ruby
11
+ gem 'coinmarketcap.rb'
12
+ ```
13
+ And then execute:
14
+ ```bash
15
+ $ bundle
16
+ ```
17
+ Or install it yourself as:
18
+ ```bash
19
+ $ gem install coinmarketcap.rb
20
+ ```
21
+
22
+ ## Notes
23
+
24
+ This gem attempts to make sense of a CoinMarketCap's somewhat confused APIs and so far only partially covers off V1 and V2 APIs. It makes sense of the V1 and V2 APIs by creating a mezzanine, API version agnostic client which will use V1 or V2 endpoints/sub-clients selectively depending on which retrieves the requested information whilst giving a cleaner and more consistent overall interface. It is likely that further abstraction/simplification of the APIs is possible, further improving the usability.
25
+
26
+ ## Usage
27
+
28
+ ### Setup
29
+ ```ruby
30
+ api_key = 'api_key0'
31
+ coinmarketcap_client ||= CoinMarketCap::Client.new(api_key: api_key)
32
+ ```
33
+
34
+ ### Airdrops
35
+ ```ruby
36
+ coinmarketcap_client.airdrops
37
+ coinmarketcap_client.airdrops(id: 123)
38
+ ```
39
+
40
+ ### Categories
41
+ ```ruby
42
+ coinmarketcap_client.categories
43
+ coinmarketcap_client.categories(id: 123)
44
+ ```
45
+
46
+ ### Gainers and Losers
47
+ ```ruby
48
+ coinmarketcap_client.gainers_and_losers
49
+ ```
50
+
51
+ ### Historical Price Data (OHLCV)
52
+ ```ruby
53
+ coinmarketcap_client.historical_price_data(id: 123)
54
+ ```
55
+
56
+ ### Historical Quotes
57
+ ```ruby
58
+ coinmarketcap_client.historical_quotes
59
+ coinmarketcap_client.historical_quotes(id: 123)
60
+ ```
61
+
62
+ ### Info for a Specific Coin
63
+ ```ruby
64
+ coinmarketcap_client.info(id: 123)
65
+ ```
66
+
67
+ ### Latest Coin Pairs Listed
68
+ ```ruby
69
+ coinmarketcap_client.latest_listings
70
+ ```
71
+
72
+ ### Latest OHLCV Price Data
73
+ ```ruby
74
+ coinmarketcap_client.latest_price_data
75
+ ```
76
+
77
+ ### Latest Performance Stats
78
+ ```ruby
79
+ coinmarketcap_client.latest_price_performance_stats
80
+ ```
81
+
82
+ ### Latest Quotes
83
+ ```ruby
84
+ coinmarketcap_client.latest_quotes
85
+ coinmarketcap_client.latest_quotes(id: 123)
86
+ ```
87
+
88
+ ### Most Visited Coins
89
+ ```ruby
90
+ coinmarketcap_client.most_visited
91
+ ```
92
+
93
+ ### Trending Coins
94
+ ```ruby
95
+ coinmarketcap_client.trending
96
+ ```
97
+
98
+ ## Contributing
99
+
100
+ 1. Fork it ( https://github.com/thoran/eodhd.rb/fork )
101
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
102
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
103
+ 4. Push to the branch (`git push origin my-new-feature`)
104
+ 5. Create a new pull request
@@ -0,0 +1,28 @@
1
+ require_relative './lib/CoinMarketCap/VERSION'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'coinmarketcap.rb'
5
+
6
+ spec.version = CoinMarketCap::VERSION
7
+ spec.date = '2025-03-30'
8
+
9
+ spec.summary = "Access the coinmarketcap.com API with Ruby."
10
+ spec.description = "Access the coinmarketcap.com API with Ruby."
11
+
12
+ spec.author = 'thoran'
13
+ spec.email = 'code@thoran.com'
14
+ spec.homepage = 'http://github.com/thoran/coinmarketcap.rb'
15
+ spec.license = 'Ruby'
16
+
17
+ spec.required_ruby_version = '>= 2.7'
18
+
19
+ spec.add_dependency('http.rb')
20
+ spec.files = [
21
+ 'coinmarketcap.rb.gemspec',
22
+ 'Gemfile',
23
+ Dir['lib/**/*.rb'],
24
+ 'README.md',
25
+ Dir['test/**/*.rb']
26
+ ].flatten
27
+ spec.require_paths = ['lib']
28
+ end
@@ -0,0 +1,92 @@
1
+ # CoinMarketCap/Client.rb
2
+ # CoinMarketCap::Client
3
+
4
+ require_relative './V1/Client'
5
+ require_relative './V2/Client'
6
+
7
+ module CoinMarketCap
8
+ class Client
9
+ def airdrops(id: nil)
10
+ if id
11
+ v1_client.airdrop(id: id)
12
+ else
13
+ v1_client.airdrops
14
+ end
15
+ end
16
+
17
+ def categories(id: nil)
18
+ if id
19
+ v1_client.category(id: id)
20
+ else
21
+ v1_client.categories
22
+ end
23
+ end
24
+
25
+ def gainers_and_losers
26
+ v1_client.trending_gainers_losers
27
+ end
28
+
29
+ def historical_price_data(id:)
30
+ v2_client.ohlcv_historical(id: id)
31
+ end
32
+
33
+ # I don't see the point of these endpoints at all. (Ha ha!) Either you want current prices or you want historical OHLCV. I don't see why having historical quotes is of any value.
34
+ def historical_quotes(id: nil)
35
+ if id
36
+ v2_client.quotes_historical(id: id)
37
+ else
38
+ v1_client.listings_historical
39
+ end
40
+ end
41
+
42
+ def info(id:)
43
+ v2_client.info(id: id)
44
+ end
45
+
46
+ def map
47
+ v1_client.map
48
+ end
49
+
50
+ def latest_listings
51
+ v2_client.market_pairs_latest
52
+ end
53
+
54
+ def latest_price_data
55
+ v2_client.ohlcv_latest
56
+ end
57
+
58
+ def most_visited
59
+ v1_client.trending_most_visited
60
+ end
61
+
62
+ def latest_price_performance_stats
63
+ v2_client.price_performance_stats_latest
64
+ end
65
+
66
+ def latest_quotes(id: nil)
67
+ if id
68
+ v2_client.quotes_latest(id: id)
69
+ else
70
+ v1_client.listings_latest
71
+ end
72
+ end
73
+
74
+ def trending
75
+ v1_client.trending_latest
76
+ end
77
+
78
+ private
79
+
80
+ def initialize(api_key:)
81
+ @api_key = api_key
82
+ end
83
+
84
+ def v1_client
85
+ @v1_client ||= CoinMarketCap::V1::Client.new(api_key: @api_key)
86
+ end
87
+
88
+ def v2_client
89
+ @v2_client ||= CoinMarketCap::V2::Client.new(api_key: @api_key)
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,61 @@
1
+ # CoinMarketCap/Common.rb
2
+ # CoinMarketCap::Common
3
+
4
+ module CoinMarketCap
5
+ class Error < RuntimeError
6
+ attr_reader :code, :message, :body
7
+
8
+ private
9
+
10
+ def initialize(code:, message:, body:)
11
+ @code = code
12
+ @message = message
13
+ @body = body
14
+ end
15
+ end
16
+
17
+ module Common
18
+ API_HOST = 'pro-api.coinmarketcap.com'
19
+
20
+ private
21
+
22
+ def initialize(api_key:)
23
+ @api_key = api_key
24
+ end
25
+
26
+ def request_string(path)
27
+ "https://#{API_HOST}#{self.class.path_prefix}#{path}"
28
+ end
29
+
30
+ def headers
31
+ {
32
+ 'Accept' => 'application/json',
33
+ 'X-CMC_PRO_API_KEY' => @api_key,
34
+ }
35
+ end
36
+
37
+ def do_request(verb:, path:, args: {})
38
+ HTTP.send(verb.to_s.downcase, request_string(path), args, headers)
39
+ end
40
+
41
+ def get(path:, args: {})
42
+ do_request(verb: 'GET', path: path, args: args)
43
+ end
44
+
45
+ def post(path:, args: {})
46
+ do_request(verb: 'POST', path: path, args: args)
47
+ end
48
+
49
+ def handle_response(response)
50
+ if response.success?
51
+ JSON.parse(response.body)
52
+ else
53
+ raise CoinMarketCap::Error.new(
54
+ code: response.code,
55
+ message: response.message,
56
+ body: response.body,
57
+ )
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,84 @@
1
+ # CoinMarketCap/V1/Client.rb
2
+ # CoinMarketCap::V1::Client
3
+
4
+ # Notes:
5
+ # 1. From https://coinmarketcap.com/api/documentation/v1/#tag/cryptocurrency
6
+ # /v1/cryptocurrency/airdrop - Airdrop
7
+ # /v1/cryptocurrency/airdrops - Airdrops
8
+ # /v1/cryptocurrency/categories - Categories
9
+ # /v1/cryptocurrency/category - Category
10
+ # /v1/cryptocurrency/listings/historical - Historical listings
11
+ # /v1/cryptocurrency/listings/latest - Latest listings
12
+ # /v1/cryptocurrency/map - CoinMarketCap ID map
13
+ # /v1/cryptocurrency/trending/gainers-losers - Trending Gainers & Losers
14
+ # /v1/cryptocurrency/trending/latest - Trending Latest
15
+ # /v1/cryptocurrency/trending/most-visited - Trending Most Visited
16
+
17
+ gem 'http.rb'
18
+ require 'http.rb'
19
+ require 'json'
20
+ require_relative '../Common'
21
+
22
+ module CoinMarketCap
23
+ module V1
24
+ class Client
25
+ include Common
26
+
27
+ class << self
28
+ def path_prefix
29
+ '/v1/cryptocurrency'
30
+ end
31
+ end # class << self
32
+
33
+ def airdrop(id:)
34
+ response = get(path: '/airdrop', args: {id: id})
35
+ handle_response(response)
36
+ end
37
+
38
+ def airdrops
39
+ response = get(path: '/airdrops')
40
+ handle_response(response)
41
+ end
42
+
43
+ def categories
44
+ response = get(path: '/categories')
45
+ handle_response(response)
46
+ end
47
+
48
+ def category(id:)
49
+ response = get(path: '/category', args: {id: id})
50
+ handle_response(response)
51
+ end
52
+
53
+ def listings_historical
54
+ response = get(path: '/listings/historical')
55
+ handle_response(response)
56
+ end
57
+
58
+ def listings_latest
59
+ response = get(path: '/listings/latest')
60
+ handle_response(response)
61
+ end
62
+
63
+ def map
64
+ response = get(path: '/map')
65
+ handle_response(response)
66
+ end
67
+
68
+ def trending_gainers_losers
69
+ response = get(path: '/trending/gainers-losers')
70
+ handle_response(response)
71
+ end
72
+
73
+ def trending_latest
74
+ response = get(path: '/trending/latest')
75
+ handle_response(response)
76
+ end
77
+
78
+ def trending_most_visited
79
+ response = get(path: '/trending/most-visited')
80
+ handle_response(response)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,67 @@
1
+ # CoinMarketCap/V2/Client.rb
2
+ # CoinMarketCap::V2::Client
3
+
4
+ # Notes:
5
+ # 1. From https://coinmarketcap.com/api/documentation/v1/#tag/cryptocurrency
6
+ # /v2/cryptocurrency/info - Metadata
7
+ # /v2/cryptocurrency/market-pairs/latest - Latest market pairs
8
+ # /v2/cryptocurrency/ohlcv/historical - Historical OHLCV
9
+ # /v2/cryptocurrency/ohlcv/latest - Latest OHLCV
10
+ # /v2/cryptocurrency/price-performance-stats/latest - Price performance Stats
11
+ # /v2/cryptocurrency/quotes/historical - Historical quotes
12
+ # /v2/cryptocurrency/quotes/latest - Latest quotes
13
+
14
+ gem 'http.rb'
15
+ require 'http.rb'
16
+ require 'json'
17
+ require_relative '../Common'
18
+
19
+ module CoinMarketCap
20
+ module V2
21
+ class Client
22
+ include Common
23
+
24
+ class << self
25
+ def path_prefix
26
+ '/v2/cryptocurrency'
27
+ end
28
+ end # class << self
29
+
30
+ def info(id:)
31
+ response = get(path: '/info', args: {id: id})
32
+ handle_response(response)
33
+ end
34
+
35
+ def market_pairs_latest
36
+ response = get(path: '/market-pairs/latest')
37
+ handle_response(response)
38
+ end
39
+
40
+ def ohlcv_historical(id:)
41
+ response = get(path: '/ohlcv/historical', args: {id: id})
42
+ handle_response(response)
43
+ end
44
+
45
+ def ohlcv_latest
46
+ response = get(path: '/ohlcv/latest')
47
+ handle_response(response)
48
+ end
49
+
50
+ def price_performance_stats_latest
51
+ response = get(path: '/price-performance-stats/latest')
52
+ handle_response(response)
53
+ end
54
+
55
+ def quotes_historical(id:)
56
+ response = get(path: '/quotes/historical', args: {id: id})
57
+ handle_response(response)
58
+ end
59
+
60
+ def quotes_latest(id:)
61
+ id = [id].compact.join(',')
62
+ response = get(path: '/quotes/latest', args: {id: id})
63
+ handle_response(response)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,6 @@
1
+ # CoinMarketCap/VERSION.rb
2
+ # CoinMarketCap::VERSION
3
+
4
+ module CoinMarketCap
5
+ VERSION = '0.3.1'
6
+ end
@@ -0,0 +1,4 @@
1
+ # CoinMarketCap.rb
2
+ # CoinMarketCap
3
+
4
+ require_relative './CoinMarketCap/Client'
@@ -0,0 +1,141 @@
1
+ require_relative '../helper'
2
+ require_relative '../../lib/CoinMarketCap/V1/Client'
3
+
4
+ describe CoinMarketCap::V1::Client do
5
+ let(:client) {CoinMarketCap::V1::Client.new(api_key: api_key)}
6
+
7
+ describe "#airdrop" do
8
+ it "returns AN airdrop" do
9
+ VCR.use_cassette('v1/cryptocurrency/airdrop') do
10
+ assert_raises CoinMarketCap::Error do
11
+ response = client.airdrop(id: 1)
12
+ # Too poor to subscribe...
13
+ # _(response).must_include('data')
14
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ describe "#airdrops" do
21
+ it "returns ALL airdrops" do
22
+ VCR.use_cassette('v1/cryptocurrency/airdrops') do
23
+ assert_raises CoinMarketCap::Error do
24
+ response = client.airdrops
25
+ # Still too poor to subscribe...
26
+ # _(response).must_include('data')
27
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "#categories" do
34
+ it "returns ALL categories" do
35
+ VCR.use_cassette('v1/cryptocurrency/categories') do
36
+ assert_raises CoinMarketCap::Error do
37
+ response = client.categories
38
+ # _(response).must_include('data')
39
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ describe "#category" do
46
+ it "returns a specific category" do
47
+ VCR.use_cassette('v1/cryptocurrency/category') do
48
+ assert_raises CoinMarketCap::Error do
49
+ response = client.category(id: 1)
50
+ # _(response).must_include('data')
51
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "#listings_historical" do
58
+ it "returns historical listings for all cryptos" do
59
+ VCR.use_cassette('v1/cryptocurrency/listings/historical') do
60
+ assert_raises CoinMarketCap::Error do
61
+ response = client.listings_historical
62
+ _(response).must_include('data')
63
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "#listings_latest" do
70
+ it "returns an array of latest prices" do
71
+ VCR.use_cassette('v1/cryptocurrency/listings/latest') do
72
+ response = client.listings_latest
73
+ _(response).must_include('data')
74
+ _(response['data']).must_be_kind_of(Array)
75
+ _(response['data'][0]).must_be_kind_of(Hash)
76
+ end
77
+ end
78
+ end
79
+
80
+ describe "#map" do
81
+ it "returns a map of crypto IDs to symbols" do
82
+ VCR.use_cassette('v1/cryptocurrency/map') do
83
+ response = client.map
84
+ _(response).must_include('data')
85
+ _(response['data'].first['symbol']).must_equal 'BTC'
86
+ end
87
+ end
88
+ end
89
+
90
+ describe "#trending_gainers_losers" do
91
+ it "returns trending gainers and losers" do
92
+ VCR.use_cassette('v1/cryptocurrency/trending/gainers-losers') do
93
+ assert_raises CoinMarketCap::Error do
94
+ response = client.trending_gainers_losers
95
+ # _(response).must_include('data')
96
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "#trending_latest" do
103
+ it "returns trending latest" do
104
+ VCR.use_cassette('v1/cryptocurrency/trending/latest') do
105
+ assert_raises CoinMarketCap::Error do
106
+ response = client.trending_latest
107
+ # _(response).must_include('data')
108
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ describe "#trending_most_visited" do
115
+ it "returns trending most visited" do
116
+ VCR.use_cassette('v1/cryptocurrency/trending/most-visited') do
117
+ assert_raises CoinMarketCap::Error do
118
+ response = client.trending_most_visited
119
+ # _(response).must_include('data')
120
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "#handle_response" do
127
+ it "handles a successful response" do
128
+ raw_response = OpenStruct.new(success?: true, body: '{"data": {}}')
129
+ response = client.send(:handle_response, raw_response)
130
+ _(response).must_include('data')
131
+ _(response).must_be_kind_of(Hash)
132
+ end
133
+
134
+ it "raises an error for a failed response" do
135
+ raw_response = OpenStruct.new(success?: false, code: 404, message: 'Not Found')
136
+ assert_raises RuntimeError do
137
+ client.send(:handle_response, raw_response)
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,111 @@
1
+ require_relative '../helper'
2
+ require_relative '../../lib/CoinMarketCap/V2/Client'
3
+
4
+ describe CoinMarketCap::V2::Client do
5
+ let(:client) {CoinMarketCap::V2::Client.new(api_key: api_key)}
6
+
7
+ describe "#info" do
8
+ it "retrieves metadata for a specific cryptocurrency" do
9
+ VCR.use_cassette('v2/cryptocurrency/info') do
10
+ response = client.info(id: 1)
11
+ _(response).must_include('data')
12
+ _(response.dig('data', '1', 'symbol')).must_equal 'BTC'
13
+ end
14
+ end
15
+ end
16
+
17
+ describe "#market_pairs_latest" do
18
+ it "retrieves the latest market pairs" do
19
+ VCR.use_cassette('v2/cryptocurrency/market-pairs/latest') do
20
+ assert_raises CoinMarketCap::Error do
21
+ response = client.market_pairs_latest
22
+ # _(response).must_include('data')
23
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ describe "#ohlcv_historical" do
30
+ it "retrieves historical OHLCV data" do
31
+ VCR.use_cassette('v2/cryptocurrency/ohlcv/historical') do
32
+ assert_raises CoinMarketCap::Error do
33
+ response = client.ohlcv_historical(id: 1)
34
+ # _(response).must_include('data')
35
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#ohlcv_latest" do
42
+ it "returns the latest OHLCV data" do
43
+ VCR.use_cassette('v2/cryptocurrency/ohlcv/latest') do
44
+ assert_raises CoinMarketCap::Error do
45
+ response = client.ohlcv_latest
46
+ # _(response).must_include('data')
47
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "#price_performance_stats_latest" do
54
+ it "retrieves the latest price performance statistics" do
55
+ VCR.use_cassette('v2/cryptocurrency/price-performance-stats/latest') do
56
+ assert_raises CoinMarketCap::Error do
57
+ response = client.price_performance_stats_latest
58
+ # _(response).must_include('data')
59
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "#quotes_historical" do
66
+ it "returns historical quotes" do
67
+ VCR.use_cassette('v2/cryptocurrency/quotes/historical') do
68
+ assert_raises CoinMarketCap::Error do
69
+ response = client.quotes_historical(id: 1)
70
+ # _(response).must_include('data')
71
+ _(JSON.parse(response.body).dig('status', 'error_message')).must_equal "Your API Key subscription plan doesn't support this endpoint."
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ describe "#quotes_latest" do
78
+ it "retrieves the latest quotes for a specific cryptocurrency" do
79
+ VCR.use_cassette('v2/cryptocurrency/quotes/latest') do
80
+ response = client.quotes_latest(id: 1)
81
+ _(response).must_include('data')
82
+ _(response['data']).must_be_kind_of(Hash)
83
+
84
+ end
85
+ end
86
+
87
+ it "retrieves quotes for multiple IDs" do
88
+ VCR.use_cassette('v2/cryptocurrency/quotes/latest_with_multiple_ids') do
89
+ response = client.quotes_latest(id: [1, 2])
90
+ _(response).must_include("data")
91
+ _(response["data"]).must_be_kind_of(Hash)
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "#handle_response" do
97
+ it "handles a successful response" do
98
+ raw_response = OpenStruct.new(success?: true, body: '{"data": {}}')
99
+ response = client.send(:handle_response, raw_response)
100
+ _(response).must_include('data')
101
+ _(response).must_be_kind_of(Hash)
102
+ end
103
+
104
+ it "raises an error for a failed response" do
105
+ response = OpenStruct.new(success?: false, code: 404, message: 'Not Found')
106
+ assert_raises RuntimeError do
107
+ client.send(:handle_response, response)
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,213 @@
1
+ require_relative './helper'
2
+ require_relative '../lib/CoinMarketCap/Client'
3
+
4
+ describe CoinMarketCap::Client do
5
+ let(:client){CoinMarketCap::Client.new(api_key: api_key)}
6
+
7
+ describe "#airdrops" do
8
+ context "when an id IS provided" do
9
+ it "calls the V1 client" do
10
+ mocked_client = Minitest::Mock.new
11
+ mocked_client.expect(:airdrop, {'data' => []}) do |kwargs|
12
+ kwargs[:id] == 1
13
+ end
14
+ client.stub :v1_client, mocked_client do
15
+ client.airdrops(id: 1)
16
+ end
17
+ mocked_client.verify
18
+ end
19
+ end
20
+
21
+ context "when an id is NOT provided" do
22
+ it "calls the V1 client" do
23
+ mocked_client = Minitest::Mock.new
24
+ mocked_client.expect :airdrops, true, []
25
+ client.stub :v1_client, mocked_client do
26
+ client.airdrops
27
+ end
28
+ mocked_client.verify
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "#categories" do
34
+ context "when an id IS provided" do
35
+ it "calls the V1 client" do
36
+ mocked_client = Minitest::Mock.new
37
+ mocked_client.expect(:category, {'data' => []}) do |kwargs|
38
+ kwargs[:id] == 1
39
+ end
40
+ client.stub :v1_client, mocked_client do
41
+ client.categories(id: 1)
42
+ end
43
+ mocked_client.verify
44
+ end
45
+ end
46
+
47
+ context "when an id is NOT provided" do
48
+ it "calls the V1 client" do
49
+ mocked_client = Minitest::Mock.new
50
+ mocked_client.expect :categories, true, []
51
+ client.stub :v1_client, mocked_client do
52
+ client.categories
53
+ end
54
+ mocked_client.verify
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "#gainers_and_losers" do
60
+ it "calls the V1 client trending_gainers_losers method" do
61
+ mocked_client = Minitest::Mock.new
62
+ mocked_client.expect :trending_gainers_losers, true, []
63
+ client.stub :v1_client, mocked_client do
64
+ client.gainers_and_losers
65
+ end
66
+ mocked_client.verify
67
+ end
68
+ end
69
+
70
+ describe "#historical_price_data" do
71
+ it "calls the V2 client" do
72
+ mocked_client = Minitest::Mock.new
73
+ mocked_client.expect(:ohlcv_historical, {'data' => []}) do |kwargs|
74
+ kwargs[:id] == 1
75
+ end
76
+ client.stub :v2_client, mocked_client do
77
+ client.historical_price_data(id: 1)
78
+ end
79
+ mocked_client.verify
80
+ end
81
+ end
82
+
83
+ describe "#historical_quotes" do
84
+ context "when an ID IS provided" do
85
+ it "calls the V2 client" do
86
+ mocked_client = Minitest::Mock.new
87
+ mocked_client.expect(:quotes_historical, {'data' => []}) do |kwargs|
88
+ kwargs[:id] == 1
89
+ end
90
+ client.stub :v2_client, mocked_client do
91
+ client.historical_quotes(id: 1)
92
+ end
93
+ mocked_client.verify
94
+ end
95
+ end
96
+
97
+ context "when no ID is provided" do
98
+ it "calls the V1 client" do
99
+ mocked_client = Minitest::Mock.new
100
+ mocked_client.expect :listings_historical, {"data" => {}}, []
101
+ client.stub :v1_client, mocked_client do
102
+ client.historical_quotes
103
+ end
104
+ mocked_client.verify
105
+ end
106
+ end
107
+ end
108
+
109
+ describe "#info" do
110
+ it "calls the V2 client" do
111
+ mocked_client = Minitest::Mock.new
112
+ mocked_client.expect(:info, {'data' => []}) do |kwargs|
113
+ kwargs[:id] == 1
114
+ end
115
+ client.stub :v2_client, mocked_client do
116
+ client.info(id: 1)
117
+ end
118
+ mocked_client.verify
119
+ end
120
+ end
121
+
122
+ describe "#map" do
123
+ it "calls the V1 client" do
124
+ mocked_client = Minitest::Mock.new
125
+ mocked_client.expect(:map, {'data' => []})
126
+ client.stub :v1_client, mocked_client do
127
+ client.map
128
+ end
129
+ mocked_client.verify
130
+ end
131
+ end
132
+
133
+ describe "#latest_listings" do
134
+ it "calls the V2 client" do
135
+ mocked_client = Minitest::Mock.new
136
+ mocked_client.expect(:market_pairs_latest, true, [])
137
+ client.stub :v2_client, mocked_client do
138
+ client.latest_listings
139
+ end
140
+ mocked_client.verify
141
+ end
142
+ end
143
+
144
+ describe "#latest_price_data" do
145
+ it "calls the V2 client" do
146
+ mocked_client = Minitest::Mock.new
147
+ mocked_client.expect(:ohlcv_latest, true, [])
148
+ client.stub :v2_client, mocked_client do
149
+ client.latest_price_data
150
+ end
151
+ mocked_client.verify
152
+ end
153
+ end
154
+
155
+ describe "#latest_price_performance_stats" do
156
+ it "calls the V2 client" do
157
+ mocked_client = Minitest::Mock.new
158
+ mocked_client.expect(:price_performance_stats_latest, true, [])
159
+ client.stub :v2_client, mocked_client do
160
+ client.latest_price_performance_stats
161
+ end
162
+ mocked_client.verify
163
+ end
164
+ end
165
+
166
+ describe "#latest_quotes" do
167
+ context "when an ID IS provided" do
168
+ it "calls the V2 client" do
169
+ mocked_client = Minitest::Mock.new
170
+ mocked_client.expect(:quotes_latest, {'data' => []}) do |kwargs|
171
+ kwargs[:id] == 1
172
+ end
173
+ client.stub :v2_client, mocked_client do
174
+ client.latest_quotes(id: 1)
175
+ end
176
+ mocked_client.verify
177
+ end
178
+ end
179
+
180
+ context "when an ID is NOT provided" do
181
+ it "calls the V1 client" do
182
+ mocked_client = Minitest::Mock.new
183
+ mocked_client.expect(:listings_latest, true, [])
184
+ client.stub :v1_client, mocked_client do
185
+ client.latest_quotes
186
+ end
187
+ mocked_client.verify
188
+ end
189
+ end
190
+ end
191
+
192
+ describe "#most_visited" do
193
+ it "calls the V1 client trending_most_visited method" do
194
+ mocked_client = Minitest::Mock.new
195
+ mocked_client.expect :trending_most_visited, true, []
196
+ client.stub :v1_client, mocked_client do
197
+ client.most_visited
198
+ end
199
+ mocked_client.verify
200
+ end
201
+ end
202
+
203
+ describe "#trending" do
204
+ it "calls the V1 client trending_latest method" do
205
+ mocked_client = Minitest::Mock.new
206
+ mocked_client.expect :trending_latest, true, []
207
+ client.stub :v1_client, mocked_client do
208
+ client.trending
209
+ end
210
+ mocked_client.verify
211
+ end
212
+ end
213
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest-spec-context'
3
+ require 'minitest/spec'
4
+ require 'ostruct'
5
+ require 'vcr'
6
+
7
+ VCR.configure do |config|
8
+ config.cassette_library_dir = File.expand_path('../fixtures/vcr_cassettes', __FILE__)
9
+ config.hook_into :webmock
10
+ end
11
+
12
+ def api_key
13
+ if ENV['COINMARKETCAP_API_KEY']
14
+ ENV['COINMARKETCAP_API_KEY']
15
+ else
16
+ 'api_key0'
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: coinmarketcap.rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - thoran
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2025-03-30 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: http.rb
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ description: Access the coinmarketcap.com API with Ruby.
27
+ email: code@thoran.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - Gemfile
33
+ - README.md
34
+ - coinmarketcap.rb.gemspec
35
+ - lib/CoinMarketCap.rb
36
+ - lib/CoinMarketCap/Client.rb
37
+ - lib/CoinMarketCap/Common.rb
38
+ - lib/CoinMarketCap/V1/Client.rb
39
+ - lib/CoinMarketCap/V2/Client.rb
40
+ - lib/CoinMarketCap/VERSION.rb
41
+ - test/V1/client_test.rb
42
+ - test/V2/client_test.rb
43
+ - test/client_test.rb
44
+ - test/helper.rb
45
+ homepage: http://github.com/thoran/coinmarketcap.rb
46
+ licenses:
47
+ - Ruby
48
+ metadata: {}
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '2.7'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.6.6
64
+ specification_version: 4
65
+ summary: Access the coinmarketcap.com API with Ruby.
66
+ test_files: []