CoinPrice fetch cryptocurrency latest prices from a Source API and cache results into an in-memory hash or Redis. Price values are returned as BigDecimal and timestamps as Integer Unix time.
NOTE: Coinpaprika is currently set as the default price Source, but there are more sources available and CoinPrice is extensible by adding more Sources.
Build and install the gem locally:
gem build coin_price.gemspec
gem install coin_price-2.1.7.gem
Or install it from rubygems.org
in your terminal:
gem install coin_price
Or via Gemfile
in your project:
source 'https://rubygems.org'
ruby '~> 2.5'
gem 'coin_price', '~> 2.1'
Require it in your Ruby code and CoinPrice
module will be available:
require 'coin_price'
CoinPrice
supports configuration with the .configure
method.
# For example, setting up to use Redis instead of local in-memory hash
CoinPrice.configure do |config|
config.redis_enabled = true
config.redis_url = 'redis://localhost:6379/0'
end
List of configuration values:
redis_enabled
: whether or not to use Redis to cache values (defaults tofalse
)redis_url
: Redis URL to cache values if enabled (defaults to'redis://localhost:6379/0'
)cache_key_prefix
: custom prefix to be used in hash or Redis keys (defaults to an empty string)default_source
: default Source to fetch prices from when none is specified (defaults to'coinpaprika'
)
(See Config
class at lib/coin_price/config.rb
for the up-to-date list of
configuration values)
NOTE: each Source may have its own configuration.
# Latest BTC price quoted in USD from Coinpaprika
CoinPrice.value('BTC', 'USD', 'coinpaprika')
# => 0.1122965353095e5
# Coinpaprika is currently set as the default source
CoinPrice.value('BTC', 'USD')
# => 0.1122965353095e5
CoinPrice.value('LTC', 'BTC')
# => 0.1056364e-1
# List many latest prices at once
CoinPrice.values(['BTC', 'ETH' , 'LTC', 'XRP'], ['USD', 'BTC', 'ETH'])
# => {
# "BTC" => {
# "USD" => 0.1122965353095e5,
# "BTC" => 0.1e1,
# "ETH" => 0.3849240929e2
# },
# "ETH" => {
# "USD" => 0.29173683167e3,
# "BTC" => 0.2600259e-1,
# "ETH" => 0.1e1
# },
# "LTC" => {
# "USD" => 0.11851911903e3,
# "BTC" => 0.1056364e-1,
# "ETH" => 0.40625353e0
# },
# "XRP" => {
# "USD" => 0.3834478e0,
# "BTC" => 0.3418e-4,
# "ETH" => 0.131436e-2
# }
# }
All fetched prices are stored into an in-memory hash or Redis and can be used instead of sending another request to the API:
CoinPrice.value('BTC', 'USD', 'coinpaprika', from_cache: true)
# => 0.1122965353095e5
CoinPrice.timestamp('BTC', 'USD', 'coinpaprika')
# => 1562352560
CoinPrice.values(['BTC', 'ETH', 'LTC', 'XRP'], ['USD', 'BTC', 'ETH'], 'coinpaprika', from_cache: true)
# Yields the same previous result for many latest prices
CoinPrice.timestamps(['BTC', 'ETH', 'LTC', 'XRP'], ['USD', 'BTC', 'ETH'], 'coinpaprika')
# Yields the same hash structure as the previous result for many latest prices,
# but with the timestamps instead of price values
# Number of requests performed today
CoinPrice.requests_count('coinpaprika')
# => 4
Keys and data
Cache keys of the in-memory hash or Redis follow the pattern:
coin-price:{source}:value:{base}:{quote}
coin-price:{source}:timestamp:{base}:{quote}
Example:
CoinPrice.cache.get('coin-price:coinpaprika:value:BTC:USD')
# => "0.1122965353095e5"
CoinPrice.cache.get('coin-price:coinpaprika:timestamp:BTC:USD')
# => "1562352560"
Or in Redis:
$ redis-cli
> get coin-price:coinpaprika:value:BTC:USD
> "0.1122965353095e5"
> get coin-price:coinpaprika:timestamp:BTC:USD
> "1562352560"
There is also a requests count at:
coin-price:{source}:requests-count:{date}
Example:
CoinPrice.cache.get('coin-price:coinpaprika:requests-count:2019-07-05')
# => "4"
Or in Redis:
$ redis-cli
> get coin-price:coinpaprika:requests-count:2019-07-05
> "4"
You can get the up-to-date list of sources with:
CoinPrice.sources
# => {
# "coinpaprika" => {
# "name" => "Coinpaprika",
# "website" => "https://coinpaprika.com/",
# "notes" => "",
# "class" => CoinPrice::Coinpaprika::Source
# },
# "coinmarketcap" => {
# "name" => "CoinMarketCap",
# "website" => "https://coinmarketcap.com/",
# "notes" => "API Key is required",
# "class" => CoinPrice::CoinMarketCap::Source
# },
# "ptax" => {
# "name" => "PTAX",
# "website" => "https://dadosabertos.bcb.gov.br/dataset/taxas-de-cambio-todos-os-boletins-diarios",
# "notes" => "Brazil's Central Bank exchange rate for USD/BRL",
# "class" => CoinPrice::PTAX::Source
# },
# "omnitrade" => {
# "name" => "Omnitrade",
# "website" => "https://omnitrade.io/",
# "notes" => "",
# "class" => CoinPrice::Omnitrade::Source
# }
# }
- ID:
'coinpaprika'
- Name: Coinpaprika
- Website: https://coinpaprika.com
CoinPrice::Coinpaprika
supports configuration with the .configure
method.
List of configuration values:
wait_between_requests
: delay in seconds between retrying a request (defaults to1
)max_request_retries
: number of retries before considering a request failed (defaults to3
)
(See Config
class at lib/coin_price/coinpaprika/config.rb
for Coinpaprika configuration values)
- ID:
'coinmarketcap'
- Name: CoinMarketCap
- Website: https://coinmarketcap.com
- Notes: API Key is required
CoinPrice::CoinMarketCap
supports configuration with the .configure
method.
Set your CoinMarketCap API Key:
CoinPrice::CoinMarketCap.configure do |config|
config.api_key = 'Your-CoinMarketCap-API-Key'
end
List of configuration values:
api_key
: your CoinMarketCap API Key (required; defaults tonil
)listings_limit
: number of results to return in the listings endpoint (defaults to200
so it consumes only 1 call credit; max limit is5000
; see https://coinmarketcap.com/api/documentation/v1/#operation/getV1CryptocurrencyListingsLatest)wait_between_requests
: delay in seconds between calls to the listings endpoint (defaults to1
)max_request_retries
: number of retries before considering a request failed (defaults to3
)
(See Config
class at lib/coin_price/coin_market_cap/config.rb
for CoinMarketCap configuration values)
- ID:
'ptax'
- Name: PTAX
- Website: https://dadosabertos.bcb.gov.br/dataset/taxas-de-cambio-todos-os-boletins-diarios
- Notes: Brazil's Central Bank exchange rate for USD/BRL
CoinPrice::PTAX
supports configuration with the .configure
method.
List of configuration values:
wait_between_requests
: delay in seconds between retrying a request (defaults to1
)max_request_retries
: number of retries before considering a request failed (defaults to3
)
(See Config
class at lib/coin_price/ptax/config.rb
for PTAX configuration values)
- ID:
'omnitrade'
- Name: Omnitrade
- Website: https://omnitrade.io
CoinPrice::Omnitrade
supports configuration with the .configure
method.
List of configuration values:
wait_between_requests
: delay in seconds between retrying a request (defaults to1
)max_request_retries
: number of retries before considering a request failed (defaults to3
)
(See Config
class at lib/coin_price/omnitrade/config.rb
for Omnitrade configuration values)
Refresher loops indefinitely and executes CoinPrice.values
to populate the
in-memory hash or Redis with the specified coin prices and source.
CoinPrice::Refresher.configure do |config|
config.wait = 60 # seconds
end
CoinPrice::Refresher.call(['BTC', 'ETH', 'LTC', 'XRP'], ['USD', 'BTC', 'ETH'], 'coinpaprika')
# Awake! Refreshing prices...
# Done refreshing prices! Sleeping...
List of configuration values:
wait
: delay in seconds to wait until the next refresh (defaults to120
)wait_weekday_multiplier
: multiplier to apply towait
on weekdays (Monday to Friday) (defaults to1
)wait_weekend_multiplier
: multiplier to apply towait
on weekends (Saturday and Sunday) (defaults to1
)
- Create a new module at
lib/coin_price/your_new_source
and implement aSource < CoinPrice::Source
class with the methodsid
andvalues
:id
must return a unique string that identifies your Source in the codevalues
must receive the paramsbases, quotes
which are arrays of currency symbols and return a hash with the price values for each base and quote pair
- Provide a test suite
- Add a group in the
SimpleCov
atspec/spec_helper.rb
- Register your new source class at
lib/coin_price/available_sources.rb
in theAVAILABLE_SOURCES
constant - Require it in
lib/coin_price.rb
Optionally implement a Config
class for you module and whichever class is
needed for it to work.
(See CoinPrice::Coinpaprika
module for an example)
Run tests with:
bundle exec rspec
Check your code style with:
bundle exec rubocop