nomics 0.1.0

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: 3b9bd275f69f7804f8a53c351ac6c6c850d5a8e3a6f02681626bf625dcca2af6
4
+ data.tar.gz: 1e822000e4c3a5c2c9caf2d1f340a5c93b1b12ea265948ce1b16f87750510fcd
5
+ SHA512:
6
+ metadata.gz: c8c6e62a107545709d628d81635d7a3e8c2ddee651e87f17d01dae62838bb5048cc7abc65375b09cbff55fb8982702ea5122640b0e116a150c3d8c7319a68ef2
7
+ data.tar.gz: 6676c9046042c4042bdfa2f21c224abf4a8a584c72231c2da47c3854dc614a73649bfbaaa75738d02469154f85f92dc2ba3723b9040530e41e8b0025323eba37
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in nomics.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ nomics (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ addressable (2.8.0)
10
+ public_suffix (>= 2.0.2, < 5.0)
11
+ crack (0.4.5)
12
+ rexml
13
+ diff-lcs (1.4.4)
14
+ hashdiff (1.0.1)
15
+ public_suffix (4.0.6)
16
+ rake (13.0.6)
17
+ rexml (3.2.5)
18
+ rspec (3.10.0)
19
+ rspec-core (~> 3.10.0)
20
+ rspec-expectations (~> 3.10.0)
21
+ rspec-mocks (~> 3.10.0)
22
+ rspec-core (3.10.1)
23
+ rspec-support (~> 3.10.0)
24
+ rspec-expectations (3.10.1)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.10.0)
27
+ rspec-mocks (3.10.2)
28
+ diff-lcs (>= 1.2.0, < 2.0)
29
+ rspec-support (~> 3.10.0)
30
+ rspec-support (3.10.2)
31
+ vcr (6.0.0)
32
+ webmock (3.14.0)
33
+ addressable (>= 2.8.0)
34
+ crack (>= 0.3.2)
35
+ hashdiff (>= 0.4.0, < 2.0.0)
36
+
37
+ PLATFORMS
38
+ x86_64-darwin-18
39
+
40
+ DEPENDENCIES
41
+ nomics!
42
+ rake (~> 13.0)
43
+ rspec (~> 3.0)
44
+ vcr
45
+ webmock
46
+
47
+ BUNDLED WITH
48
+ 2.2.22
data/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # Nomics
2
+
3
+ [Nomics](https://p.nomics.com/about) is an API-first cryptoasset data company delivering professional-grade market data APIs to institutional crypto investors & exchanges. This gem provides Ruby bindings to its V1 API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'nomics'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install nomics
20
+
21
+ ## Usage
22
+
23
+ First, configure Nomics. You can use the `NOMICS_API_KEY` env var or using a block:
24
+
25
+ ```ruby
26
+ Nomics.configure do |config|
27
+ # Get an API key at https://p.nomics.com/pricing
28
+ # This defaults to ENV['NOMICS_API_KEY']
29
+ config.api_key = 'abcd1234'.freeze
30
+
31
+ # If you have a free API key that is limited to one call per second,
32
+ # you can add 2 seconds before network calls:
33
+ config.wait_time_in_between_calls = 2
34
+ end
35
+ ```
36
+
37
+ ### Getting currency data
38
+
39
+ Create a currency object and fetch some data on it
40
+ ```ruby
41
+ btc = Nomics::Currency.new('BTC') # also supports symbols like Nomics::Currency.new(:BTC)
42
+ ```
43
+
44
+ Let's see some data!
45
+ ```ruby
46
+ btc.price
47
+ btc.name
48
+ ```
49
+
50
+ Get all the known attributes (casted for convenience) for a given currency:
51
+ ```ruby
52
+ btc.attributes
53
+ ```
54
+ You can reload the data from the Nomics API with a single call. Here's how you'd get an up-to-date price:
55
+ ```ruby
56
+ btc.reload.price
57
+ ```
58
+
59
+ If a currency cannot be found, it will raise an error (once we fetch any data):
60
+ ```ruby
61
+ bazinga = Nomics::Currency.new('BAZINGA')
62
+ bazinga.price
63
+ # => Cannot find currency with id: BAZINGA (Nomics::UnknownCurrencyError)
64
+ ```
65
+
66
+ ### Fetching multiple currencies at once
67
+
68
+ You can fetch multiple currencies using a single call and fetch all attributes:
69
+
70
+ ```ruby
71
+ currencies = Nomics::Currencies.new(*%w[BTC XRP ETH])
72
+ currencies.map &:attributes
73
+ ```
74
+
75
+ If you want to view a specific set of attributes for the currencies provided, you can map over them:
76
+
77
+ ```ruby
78
+ currencies = Nomics::Currencies.new(*%w[ETH BTC])
79
+
80
+ currencies.map &:circulating_supply
81
+ currencies.map &:name
82
+ currencies.map &:symbol
83
+ currencies.map &:price
84
+ ```
85
+
86
+ Alternatively you simply just pluck these (similar to how ActiveRecord works)
87
+
88
+ ```ruby
89
+ currencies.pluck :circulating_supply, :name, :symbol, :price
90
+ ```
91
+
92
+ ### Retrieving currencies in given fiat
93
+
94
+ Retrieving a specific cryptocurrency in a specific fiat currency can also be done. This will quote ticker price, market cap, and volume in the specified currency:
95
+
96
+ ```ruby
97
+ btc_in_zar = Nomics::Currency.new('BTC', convert: 'EUR')
98
+ eth_in_usd = Nomics::Currency.new('ETH', convert: 'USD')
99
+ eth_in_usd = Nomics::Currency.new('ETH') # convert defaults to USD
100
+ ```
101
+
102
+ ### Calculating the price of one cryptocurrency from another
103
+
104
+ Advanced calculations are yet under consideration for this gem, but you can calculate prices in relation to their dollar value. For example:
105
+
106
+ ```ruby
107
+ btc_price_in_usd = Nomics::Currency.new('BTC').price.to_f # Nomics API defaults to USD
108
+ eth_price_in_usd = Nomics::Currency.new('ETH').price.to_f # Nomics API defaults to USD
109
+
110
+ eth_price_in_btc = eth_price_in_usd / btc_price_in_usd
111
+ ```
112
+
113
+ ## Development
114
+
115
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
116
+
117
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
118
+
119
+ ## Contributing
120
+
121
+ Bug reports and pull requests are welcome on GitHub at https://github.com/attilagyorffy/nomics.rb.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "nomics"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,43 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'json'
4
+ module Nomics
5
+ class Client
6
+
7
+ # NOMICS_BASE_URL = "https://api.nomics.com"
8
+
9
+ def get(path, params = {})
10
+ params.merge!(key: api_key)
11
+
12
+ uri = URI::HTTPS.build(host: 'api.nomics.com', path: path, query: URI.encode_www_form(params))
13
+
14
+ wait_if_necessary
15
+ response = Net::HTTP.get_response(uri)
16
+
17
+ case response
18
+ when Net::HTTPSuccess
19
+ JSON.parse response.body
20
+ when Net::HTTPUnauthorized
21
+ raise HTTPAuthorizationError.new(response.body)
22
+ when Net::HTTPServerError
23
+ raise APIServerError.new(response.body)
24
+ else
25
+ raise UnhandledError.new(response.body)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def api_key
32
+ ::Nomics.configuration.api_key || raise(HTTPAuthorizationError, "Missing API key. Forgot to set ENV['NOMICS_API_KEY'] or Nomics.configuration.api_key?")
33
+ end
34
+
35
+ # Nomics.com’s free plan allows for 1 request per second. This allows us to wait in between calls.
36
+ # TODO: Rescue from the specific nomics authorization error and implement automatic waiting in between calls
37
+ def wait_if_necessary
38
+ if seconds = ::Nomics.configuration.wait_time_in_between_calls
39
+ sleep seconds
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ module Nomics
2
+ class Configuration
3
+ attr_accessor :api_key, :wait_time_in_between_calls
4
+
5
+ def initialize
6
+ @api_key = ENV['NOMICS_API_KEY']
7
+ @wait_time_in_between_calls = nil
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,33 @@
1
+ module Nomics
2
+ class Currencies
3
+ include Enumerable
4
+
5
+ def initialize(*currencies)
6
+ @currencies = currencies.map { |symbol| Currency.new(symbol) }
7
+ end
8
+
9
+ def each
10
+ @currencies.map { |currency| yield currency }
11
+ end
12
+
13
+ def last
14
+ @currencies.last
15
+ end
16
+
17
+ def pluck(*attributes)
18
+ if attributes.one?
19
+ map { |currency| currency.send(attributes.first) }
20
+ else
21
+ map do |currency|
22
+ [].tap do |data|
23
+ attributes.each { |attribute| data << currency.send(attribute) }
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def reload
30
+ @currencies.each &:reload
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,103 @@
1
+ require 'time'
2
+ require 'bigdecimal'
3
+
4
+ module Nomics
5
+ class Currency
6
+ ATTTRIBUTES_WITH_TYPES = {
7
+ 'id' => :string,
8
+ 'currency' => :string,
9
+ 'symbol' => :symbol,
10
+ 'name' => :string,
11
+ 'logo_url' => :string,
12
+ 'status' => :string,
13
+ 'price' => :number,
14
+ 'price_date' => :timestamp,
15
+ 'price_timestamp' => :timestamp,
16
+ 'circulating_supply' => :number,
17
+ 'max_supply' => :number,
18
+ 'market_cap' => :number,
19
+ 'market_cap_dominance' => :number,
20
+ 'num_exchanges' => :number,
21
+ 'num_pairs' => :number,
22
+ 'num_pairs_unmapped' => :number,
23
+ 'first_candle' => :timestamp,
24
+ 'first_trade' => :timestamp,
25
+ 'first_order_book' => :timestamp,
26
+ 'rank' => :number,
27
+ 'rank_delta' => :number,
28
+ 'high' => :number,
29
+ 'high_timestamp' => :timestamp
30
+ }.freeze
31
+
32
+ attr_reader :symbol, :quote_currency
33
+
34
+ def initialize(symbol, convert: :USD)
35
+ @symbol = symbol.to_s.upcase.to_sym
36
+ @quote_currency = convert.to_s.upcase.to_sym
37
+
38
+ ATTTRIBUTES_WITH_TYPES.except('symbol').keys.each do |attribute_name|
39
+ instance_variable_set("@#{attribute_name}", nil)
40
+ end
41
+ end
42
+
43
+ def <=>(other_currency)
44
+ name <=> other_currency.name
45
+ end
46
+
47
+ ATTTRIBUTES_WITH_TYPES.except('symbol').each do |(attribute_name, attribute_type)|
48
+ define_method(attribute_name) do
49
+ attributes[attribute_name]
50
+ end
51
+ end
52
+
53
+ def attributes(reload: false)
54
+ if reload
55
+ @attributes = attributes_with_types data.slice(*ATTTRIBUTES_WITH_TYPES.keys)
56
+ else
57
+ @attributes ||= attributes_with_types data.slice(*ATTTRIBUTES_WITH_TYPES.keys)
58
+ end
59
+
60
+ @attributes.each do |(attribute_name, attribute_value)|
61
+ instance_variable_set("@#{attribute_name}", attribute_value)
62
+ end
63
+ end
64
+
65
+ def reload
66
+ attributes reload: true
67
+ self
68
+ end
69
+
70
+ private
71
+
72
+ def attributes_with_types(attributes = {})
73
+ attributes.inject({}) do |typed_attributes, (attribute_key, attribute_value)|
74
+ typed_attributes[attribute_key] = cast value: attribute_value, type: ATTTRIBUTES_WITH_TYPES[attribute_key]
75
+
76
+ typed_attributes
77
+ end
78
+ end
79
+
80
+ def cast(value:, type:)
81
+ case type
82
+ when :string
83
+ value.to_s
84
+ when :symbol
85
+ value.to_sym
86
+ when :number
87
+ BigDecimal(value)
88
+ when :timestamp
89
+ Time.parse(value)
90
+ else
91
+ raise "Unknown type: #{attribute_type}"
92
+ end
93
+ end
94
+
95
+ def data
96
+ client.get('/v1/currencies/ticker', ids: [@symbol], convert: @quote_currency).first || raise(Nomics::UnknownCurrencyError.new("Cannot find currency with id: #{@symbol}"))
97
+ end
98
+
99
+ def client
100
+ @client ||= Client.new
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nomics
4
+ VERSION = "0.1.0"
5
+ end
data/lib/nomics.rb ADDED
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "nomics/version"
4
+
5
+ module Nomics
6
+ class HTTPAuthorizationError < StandardError; end
7
+ class APIServerError < StandardError; end
8
+ class UnknownCurrencyError < StandardError; end
9
+ class UnhandledError < StandardError; end
10
+
11
+ autoload(:Configuration, 'nomics/configuration')
12
+ autoload(:Client, 'nomics/client')
13
+ autoload(:Currency, 'nomics/currency')
14
+ autoload(:Currencies, 'nomics/currencies')
15
+
16
+ class << self
17
+ def configuration
18
+ @configuration ||= Configuration.new
19
+ end
20
+
21
+ def configure
22
+ yield configuration
23
+ end
24
+ end
25
+ end
data/nomics.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/nomics/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "nomics"
7
+ spec.version = Nomics::VERSION
8
+ spec.authors = ["Attila Györffy"]
9
+ spec.email = ["attila@attilagyorffy.com"]
10
+
11
+ spec.summary = "A Ruby client for the Nomics Cryptocurrency API"
12
+ spec.description = "A Ruby client for the Nomics Cryptocurrency API"
13
+ spec.homepage = "https://nomics.com/docs/"
14
+ spec.required_ruby_version = ">= 2.4.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+
18
+ # Specify which files should be added to the gem when it is released.
19
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
22
+ end
23
+ spec.bindir = "exe"
24
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
25
+ spec.require_paths = ["lib"]
26
+
27
+ spec.add_development_dependency "rspec"
28
+ spec.add_development_dependency "webmock"
29
+ spec.add_development_dependency "vcr"
30
+
31
+ # For more information and examples about making a new gem, checkout our
32
+ # guide at: https://bundler.io/guides/creating_gem.html
33
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nomics
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Attila Györffy
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-10-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: webmock
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: vcr
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A Ruby client for the Nomics Cryptocurrency API
56
+ email:
57
+ - attila@attilagyorffy.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - Gemfile
65
+ - Gemfile.lock
66
+ - README.md
67
+ - Rakefile
68
+ - bin/console
69
+ - bin/setup
70
+ - lib/nomics.rb
71
+ - lib/nomics/client.rb
72
+ - lib/nomics/configuration.rb
73
+ - lib/nomics/currencies.rb
74
+ - lib/nomics/currency.rb
75
+ - lib/nomics/version.rb
76
+ - nomics.gemspec
77
+ homepage: https://nomics.com/docs/
78
+ licenses: []
79
+ metadata:
80
+ homepage_uri: https://nomics.com/docs/
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 2.4.0
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubygems_version: 3.2.22
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: A Ruby client for the Nomics Cryptocurrency API
100
+ test_files: []