justcoin 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dce2808b59479b8c626696ccf4e2fadd96c7531d
4
+ data.tar.gz: f7332649f19c6110d501a5b1f30cdc106d900a41
5
+ SHA512:
6
+ metadata.gz: ef93767a6f8883450a4d0c84c0451ea992d638b6580e806f21079f7b7f76d340ca2eeb72571364a20905642a07c8c7e189a2c83ec26eed062978443701eb133a
7
+ data.tar.gz: 3c756192a10d3dddf5fd4b3b34934bdfeedd9e157da7ae2fe3489cdec501dbdb2bfd8cad552c9cf7a4fa7b0048f3491602cf7be896aec0577e237608aa4aeafb
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in justcoin.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Laszlo Bacsi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ # Justcoin
2
+
3
+ An API client for [Justcoin](https://justcoin.com/?r=VLM7U).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'justcoin'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install justcoin
18
+
19
+ ## Usage
20
+
21
+ * [Documentation](http://rubydoc.info/github/lackac/justcoin)
22
+
23
+ ### Example
24
+
25
+ ``` ruby
26
+ client = Justcoin.new(ENV['JUSTCOIN_KEY'])
27
+
28
+ # fetch current BTC balance
29
+ btc = client.balances.detect {|b| b.currency == "BTC"}
30
+
31
+ # fetch market stats for BTCSTR
32
+ btcstr = client.markets.detect {|m| m.id == "BTCSTR"}
33
+
34
+ # sell half of available BTC for STR in a limit order
35
+ client.place_order(:btcstr, :ask, btcstr.ask-0.001, btc.available/2)
36
+ ```
37
+
38
+ ## Contributing
39
+
40
+ 1. Fork it
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create new Pull Request
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'justcoin/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "justcoin"
8
+ spec.version = Justcoin::VERSION
9
+ spec.authors = ["Laszlo Bacsi"]
10
+ spec.email = ["lackac@lackac.hu"]
11
+ spec.description = %q{Justcoin API client}
12
+ spec.summary = %q{Justcoin API client}
13
+ spec.homepage = "https://github.com/lackac/justcoin"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "faraday"
22
+ spec.add_dependency "faraday_middleware"
23
+ spec.add_dependency "hashie"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.3"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec"
28
+ spec.add_development_dependency "webmock"
29
+ end
@@ -0,0 +1,134 @@
1
+ require "faraday"
2
+ require "faraday_middleware"
3
+
4
+ require "justcoin/version"
5
+ require "justcoin/body_extractor"
6
+ require "justcoin/decimal_converter"
7
+
8
+ class Justcoin
9
+
10
+ DEFAULT_URL = "https://justcoin.com/api/v1".freeze
11
+
12
+ attr_reader :key, :options, :client
13
+
14
+ # Creates a new Justcoin client.
15
+ #
16
+ # @param key the API key, get it from
17
+ # https://justcoin.com/client/#settings/apikeys
18
+ # @param options the client can receive the following options
19
+ # * `:log` [true/false] – whether to log requests and responses
20
+ # * `:logger` [Logger] – a custom logger instance, implies `log: true`
21
+ # * `:raw` [true/false] – whether to return the raw Faraday::Response object instead of a parsed value
22
+ # * any other options are passed on to the Faraday client
23
+ def initialize(key, options={})
24
+ @key = key
25
+
26
+ options[:url] ||= DEFAULT_URL
27
+ options[:params] ||= {}
28
+ options[:params][:key] ||= key
29
+ options[:headers] ||= {}
30
+ options[:headers][:user_agent] ||= "Justcoin ruby client v#{Justcoin::VERSION}"
31
+ @options = options
32
+
33
+ @client = build_client
34
+ end
35
+
36
+ # List balances
37
+ #
38
+ # @return [Array] an array of current balances
39
+ def balances
40
+ client.get "balances"
41
+ end
42
+
43
+ # List markets
44
+ #
45
+ # @return [Array] an array of markets with current statistics
46
+ def markets
47
+ client.get "markets"
48
+ end
49
+
50
+ # Retrieve market depth
51
+ #
52
+ # @param [String/Symbol] id the id of the market (e.g. `:btcstr`)
53
+ # @return [Hashie::Mash] `bids` and `asks` as arrays of `[price, volume]` pairs
54
+ def market_depth(id)
55
+ client.get "markets/#{id.upcase}/depth"
56
+ end
57
+
58
+ # Retrieve active user orders
59
+ #
60
+ # @return [Array] an array of the user's active orders
61
+ def orders
62
+ client.get "orders"
63
+ end
64
+
65
+ # Retrieve a specific user order
66
+ #
67
+ # Works for all kinds of orders: active, cancelled, or historical.
68
+ #
69
+ # @param id the id of the order
70
+ # @return [Hashie::Mash] information about the order including matches
71
+ def order(id)
72
+ client.get "orders/#{id}"
73
+ end
74
+
75
+ # Create an order
76
+ #
77
+ # @param [String/Symbol] market the id of the market (e.g. `:btcstr`)
78
+ # @param type the order type; can be `:bid` (buy base currency) or `:ask` (sell base currency)
79
+ # @param [Numeric/String/nil] price the order price; if set to `nil`,
80
+ # the order is placed as a market order
81
+ # @param [Numeric/String] amount the amount of base currency
82
+ # (identified by the first three letters of the market id) to buy/sell
83
+ # @return [Hashie::Mash] includes the order id if the order is successfully created
84
+ def create_order(market, type, price, amount)
85
+ type = type.downcase.to_sym
86
+ raise ArgumentError, "type must be either :bid or :ask" unless [:bid, :ask].include?(type)
87
+
88
+ params = {
89
+ market: market.upcase,
90
+ type: type,
91
+ price: price,
92
+ amount: amount
93
+ }
94
+
95
+ client.post "orders", params
96
+ end
97
+ alias_method :place_order, :create_order
98
+
99
+ # Cancel the remainder of the specified order
100
+ #
101
+ # @param id the id of the order
102
+ # @return true if cancelling the order was successful
103
+ def cancel_order(id)
104
+ client.delete("orders/#{id}") == ""
105
+ end
106
+
107
+ private
108
+
109
+ def client_options
110
+ options.select { |k,v| Faraday::ConnectionOptions.members.include?(k) }
111
+ end
112
+
113
+ def build_client
114
+ Faraday.new(client_options) do |f|
115
+ unless options[:raw]
116
+ # This extracts the body and discards all other data from the
117
+ # Faraday::Response object. It should be placed here in the middle
118
+ # of the stack so that it runs as the last one.
119
+ f.use Justcoin::BodyExtractor
120
+ f.use Justcoin::DecimalConverter
121
+ end
122
+
123
+ f.request :json
124
+ f.response :mashify
125
+ f.response :dates
126
+ f.response :json, content_type: /\bjson$/
127
+ f.response :logger, options[:logger] if options[:logger] || options[:log]
128
+ f.response :raise_error
129
+
130
+ f.adapter Faraday.default_adapter
131
+ end
132
+ end
133
+
134
+ end
@@ -0,0 +1,10 @@
1
+ class Justcoin
2
+ class BodyExtractor < Faraday::Middleware
3
+
4
+ def call(env)
5
+ response = @app.call(env)
6
+ response.env[:body]
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,41 @@
1
+ require "bigdecimal"
2
+
3
+ class Justcoin
4
+ class DecimalConverter < Faraday::Middleware
5
+
6
+ def call(env)
7
+ convert_decimals(env.body) if env.body
8
+ response = @app.call(env)
9
+ parse_response response.env[:body]
10
+ response
11
+ end
12
+
13
+ private
14
+
15
+ def convert_decimals(body)
16
+ %i(price amount).each do |key|
17
+ case body[key]
18
+ when BigDecimal
19
+ body[key] = body[key].to_s("F")
20
+ when Numeric
21
+ body[key] = Float(body[key]).to_s
22
+ end
23
+ end
24
+ end
25
+
26
+ def parse_response(value)
27
+ case value
28
+ when Array
29
+ value.map! {|v| parse_response(v)}
30
+ when Hash, Hashie::Mash
31
+ value.each do |k, v|
32
+ value[k] = parse_response(v)
33
+ end
34
+ when /^\s*\d*\.\d+/
35
+ value = BigDecimal.new(value)
36
+ end
37
+ value
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ class Justcoin
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,18 @@
1
+ HTTP/1.1 200 OK
2
+ Accept-Ranges: bytes
3
+ Access-Control-Allow-Headers: Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
4
+ Access-Control-Allow-Methods: GET, POST, OPTIONS, PATCH, DELETE
5
+ Access-Control-Allow-Origin: *
6
+ Age: 0
7
+ cache-control: max-age=0
8
+ Content-Type: application/json; charset=utf-8
9
+ Date: Sun, 17 Aug 2014 23:12:03 GMT
10
+ ETag: W/"247-4257643789"
11
+ Strict-Transport-Security: max-age=31536000
12
+ X-Cache: MISS
13
+ X-Frame-Options: DENY
14
+ X-XSS-Protection: 1; mode=block
15
+ Content-Length: 583
16
+ Connection: keep-alive
17
+
18
+ [{"currency":"USD","balance":"0.00000","hold":"0.00000","available":"0.00000"},{"currency":"STR","balance":"5000.00000000","hold":"0.00000000","available":"5000.00000000"},{"currency":"BTC","balance":"0.00000840","hold":"0.00000000","available":"0.00000840"},{"currency":"EUR","balance":"0.00000","hold":"0.00000","available":"0.00000"},{"currency":"NOK","balance":"0.00000","hold":"0.00000","available":"0.00000"},{"currency":"LTC","balance":"0.00000000","hold":"0.00000000","available":"0.00000000"},{"currency":"XRP","balance":"0.114568","hold":"0.000000","available":"0.114568"}]
@@ -0,0 +1,14 @@
1
+ HTTP/1.1 204 No Content
2
+ Accept-Ranges: bytes
3
+ Access-Control-Allow-Headers: Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
4
+ Access-Control-Allow-Methods: GET, POST, OPTIONS, PATCH, DELETE
5
+ Access-Control-Allow-Origin: *
6
+ Age: 0
7
+ cache-control: max-age=0
8
+ Date: Wed, 20 Aug 2014 20:02:00 GMT
9
+ Strict-Transport-Security: max-age=31536000
10
+ X-Cache: MISS
11
+ X-Frame-Options: DENY
12
+ X-XSS-Protection: 1; mode=block
13
+ Connection: keep-alive
14
+
@@ -0,0 +1,11 @@
1
+ HTTP/1.1 201 Created
2
+ Accept-Ranges: bytes
3
+ Age: 0
4
+ cache-control: max-age=0
5
+ Content-Type: application/json; charset=utf-8
6
+ Date: Wed, 20 Aug 2014 15:50:00 GMT
7
+ X-Cache: MISS
8
+ Content-Length: 14
9
+ Connection: keep-alive
10
+
11
+ {"id":4089635}
@@ -0,0 +1,17 @@
1
+ HTTP/1.1 200 OK
2
+ Access-Control-Allow-Headers: Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
3
+ Access-Control-Allow-Methods: GET, POST, OPTIONS, PATCH, DELETE
4
+ Access-Control-Allow-Origin: *
5
+ Age: 0
6
+ cache-control: max-age=0
7
+ Content-Type: application/json; charset=utf-8
8
+ Date: Tue, 19 Aug 2014 15:07:08 GMT
9
+ ETag: W/"6d17-2515187714"
10
+ Strict-Transport-Security: max-age=31536000
11
+ X-Cache: MISS
12
+ X-Frame-Options: DENY
13
+ X-XSS-Protection: 1; mode=block
14
+ transfer-encoding: chunked
15
+ Connection: keep-alive
16
+
17
+ {"bids":[["226244.000","0.07020"],["225502.260","0.30000"],["225500.000","0.01651"],["225392.260","0.00200"]],"asks":[["226697.000","0.88946"],["226698.000","3.30000"],["226800.000","0.59715"],["226900.000","1.53781"]]}
@@ -0,0 +1,18 @@
1
+ HTTP/1.1 200 OK
2
+ Accept-Ranges: bytes
3
+ Access-Control-Allow-Headers: Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
4
+ Access-Control-Allow-Methods: GET, POST, OPTIONS, PATCH, DELETE
5
+ Access-Control-Allow-Origin: *
6
+ Age: 0
7
+ cache-control: max-age=0
8
+ Content-Type: application/json; charset=utf-8
9
+ Date: Sun, 17 Aug 2014 23:57:18 GMT
10
+ ETag: W/"31a-1371539062"
11
+ Strict-Transport-Security: max-age=31536000
12
+ X-Cache: MISS
13
+ X-Frame-Options: DENY
14
+ X-XSS-Protection: 1; mode=block
15
+ Content-Length: 794
16
+ Connection: keep-alive
17
+
18
+ [{"id":"BTCEUR","last":"376.777","high":"427.000","low":"371.112","bid":"371.760","ask":"385.410","volume":"16.88278","scale":3},{"id":"BTCLTC","last":"110.999","high":"111.000","low":"86.001","bid":"92.001","ask":"110.999","volume":"2.81474","scale":3},{"id":"BTCNOK","last":"3072.001","high":"3275.149","low":"3072.000","bid":"3075.034","ask":"3110.850","volume":"7.82705","scale":3},{"id":"BTCSTR","last":"210987.890","high":"212303.000","low":"201016.000","bid":"209090.100","ask":"210987.890","volume":"75.07222","scale":3},{"id":"BTCUSD","last":"500.714","high":"533.620","low":"488.501","bid":"495.751","ask":"513.999","volume":"3.92299","scale":3},{"id":"BTCXRP","last":"96800.000","high":"102762.000","low":"93100.000","bid":"93700.714","ask":"96800.000","volume":"7.71935","scale":3}]
@@ -0,0 +1,18 @@
1
+ HTTP/1.1 200 OK
2
+ Accept-Ranges: bytes
3
+ Access-Control-Allow-Headers: Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
4
+ Access-Control-Allow-Methods: GET, POST, OPTIONS, PATCH, DELETE
5
+ Access-Control-Allow-Origin: *
6
+ Age: 0
7
+ cache-control: max-age=0
8
+ Content-Type: application/json; charset=utf-8
9
+ Date: Tue, 19 Aug 2014 15:44:40 GMT
10
+ ETag: W/"183-2393636014"
11
+ Strict-Transport-Security: max-age=31536000
12
+ X-Cache: MISS
13
+ X-Frame-Options: DENY
14
+ X-XSS-Protection: 1; mode=block
15
+ Content-Length: 387
16
+ Connection: keep-alive
17
+
18
+ {"id":3901787,"createdAt":"2014-08-13T09:44:14.093Z","market":"BTCSTR","type":"ask","price":"197999.000","original":"0.08030","matched":"0.08030","canceled":"0.00000","remaining":"0.00000","matches":[{"id":186158,"createdAt":"2014-08-13T09:44:53.274Z","price":"197999.000","amount":"0.00522"},{"id":186159,"createdAt":"2014-08-13T09:45:00.747Z","price":"197999.000","amount":"0.07508"}]}
@@ -0,0 +1,18 @@
1
+ HTTP/1.1 200 OK
2
+ Accept-Ranges: bytes
3
+ Access-Control-Allow-Headers: Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
4
+ Access-Control-Allow-Methods: GET, POST, OPTIONS, PATCH, DELETE
5
+ Access-Control-Allow-Origin: *
6
+ Age: 0
7
+ cache-control: max-age=0
8
+ Content-Type: application/json; charset=utf-8
9
+ Date: Tue, 19 Aug 2014 15:30:30 GMT
10
+ ETag: W/"17b-2033545919"
11
+ Strict-Transport-Security: max-age=31536000
12
+ X-Cache: MISS
13
+ X-Frame-Options: DENY
14
+ X-XSS-Protection: 1; mode=block
15
+ Content-Length: 379
16
+ Connection: keep-alive
17
+
18
+ [{"id":4054198,"market":"BTCSTR","type":"ask","price":"229494.000","amount":"0.00436","remaining":"0.00436","matched":"0.00000","cancelled":"0.00000","createdAt":"2014-08-19T10:18:55.582Z"},{"id":4054182,"market":"BTCSTR","type":"bid","price":"216777.000","amount":"0.00459","remaining":"0.00459","matched":"0.00000","cancelled":"0.00000","createdAt":"2014-08-19T10:17:55.622Z"}]
@@ -0,0 +1,171 @@
1
+ require 'spec_helper'
2
+
3
+ describe Justcoin do
4
+
5
+ let(:justcoin) { Justcoin.new("somekey") }
6
+
7
+ it "should have a version number" do
8
+ expect(Justcoin::VERSION).to_not be_nil
9
+ end
10
+
11
+ describe '#initialize' do
12
+ it "builds a client" do
13
+ expect(justcoin.client).to respond_to(:get)
14
+ end
15
+ end
16
+
17
+ describe '#balances' do
18
+ before do
19
+ stub_get('/balances').with(query: {key: "somekey"}).to_return(fixture("balances.json"))
20
+ end
21
+
22
+ it "returns the current balances in a hash of currencies" do
23
+ response = justcoin.balances
24
+ str = response.detect {|x| x.currency == "STR"}
25
+ expect(str.balance).to eq(bd("5000.0"))
26
+ expect(response.map(&:to_hash)).to eq([
27
+ {'currency' => "USD", 'balance' => bd("0.0"), 'hold' => bd("0.0"), 'available' => bd("0.0")},
28
+ {'currency' => "STR", 'balance' => bd("5000.0"), 'hold' => bd("0.0"), 'available' => bd("5000.0")},
29
+ {'currency' => "BTC", 'balance' => bd("0.0000084"), 'hold' => bd("0.0"), 'available' => bd("0.0000084")},
30
+ {'currency' => "EUR", 'balance' => bd("0.0"), 'hold' => bd("0.0"), 'available' => bd("0.0")},
31
+ {'currency' => "NOK", 'balance' => bd("0.0"), 'hold' => bd("0.0"), 'available' => bd("0.0")},
32
+ {'currency' => "LTC", 'balance' => bd("0.0"), 'hold' => bd("0.0"), 'available' => bd("0.0")},
33
+ {'currency' => "XRP", 'balance' => bd("0.114568"), 'hold' => bd("0.0"), 'available' => bd("0.114568")}
34
+ ])
35
+ end
36
+
37
+ context "with raw: true" do
38
+ let(:justcoin) { Justcoin.new("somekey", raw: true) }
39
+
40
+ it "returns the raw Faraday::Response object" do
41
+ response = justcoin.balances
42
+ expect(response).to be_a(Faraday::Response)
43
+ expect(response).to be_success
44
+ expect(response.status).to eq(200)
45
+ expect(response.body.first).to be_a(Hashie::Mash)
46
+ expect(response.body.map(&:to_hash)).to eq([
47
+ {"currency"=>"USD", "balance"=>"0.00000", "hold"=>"0.00000", "available"=>"0.00000"},
48
+ {"currency"=>"STR", "balance"=>"5000.00000000", "hold"=>"0.00000000", "available"=>"5000.00000000"},
49
+ {"currency"=>"BTC", "balance"=>"0.00000840", "hold"=>"0.00000000", "available"=>"0.00000840"},
50
+ {"currency"=>"EUR", "balance"=>"0.00000", "hold"=>"0.00000", "available"=>"0.00000"},
51
+ {"currency"=>"NOK", "balance"=>"0.00000", "hold"=>"0.00000", "available"=>"0.00000"},
52
+ {"currency"=>"LTC", "balance"=>"0.00000000", "hold"=>"0.00000000", "available"=>"0.00000000"},
53
+ {"currency"=>"XRP", "balance"=>"0.114568", "hold"=>"0.000000", "available"=>"0.114568"}
54
+ ])
55
+ end
56
+ end
57
+ end
58
+
59
+ describe '#markets' do
60
+ before do
61
+ stub_get('/markets').with(query: {key: "somekey"}).to_return(fixture("markets.json"))
62
+ end
63
+
64
+ it "returns the current market statistics" do
65
+ response = justcoin.markets
66
+ expect(response.first.high).to eq(bd("427.0"))
67
+ expect(response.map(&:to_hash)).to eq([
68
+ {'id' => "BTCEUR", 'last' => bd("376.777"), 'high' => bd("427.0"), 'low' => bd("371.112"), 'bid' => bd("371.76"), 'ask' => bd("385.41"), 'volume' => bd("16.88278"), 'scale' => 3},
69
+ {'id' => "BTCLTC", 'last' => bd("110.999"), 'high' => bd("111.0"), 'low' => bd("86.001"), 'bid' => bd("92.001"), 'ask' => bd("110.999"), 'volume' => bd("2.81474"), 'scale' => 3},
70
+ {'id' => "BTCNOK", 'last' => bd("3072.001"), 'high' => bd("3275.149"), 'low' => bd("3072.0"), 'bid' => bd("3075.034"), 'ask' => bd("3110.85"), 'volume' => bd("7.82705"), 'scale' => 3},
71
+ {'id' => "BTCSTR", 'last' => bd("210987.89"), 'high' => bd("212303.0"), 'low' => bd("201016.0"), 'bid' => bd("209090.1"), 'ask' => bd("210987.89"), 'volume' => bd("75.07222"), 'scale' => 3},
72
+ {'id' => "BTCUSD", 'last' => bd("500.714"), 'high' => bd("533.62"), 'low' => bd("488.501"), 'bid' => bd("495.751"), 'ask' => bd("513.999"), 'volume' => bd("3.92299"), 'scale' => 3},
73
+ {'id' => "BTCXRP", 'last' => bd("96800.0"), 'high' => bd("102762.0"), 'low' => bd("93100.0"), 'bid' => bd("93700.714"), 'ask' => bd("96800.0"), 'volume' => bd("7.71935"), 'scale' => 3}
74
+ ])
75
+ end
76
+ end
77
+
78
+ describe '#market_depth' do
79
+ before do
80
+ stub_get('/markets/BTCSTR/depth').with(query: {key: "somekey"}).to_return(fixture("market_depth.json"))
81
+ end
82
+
83
+ it "returns the current orders for the given market as arrays of bids and asks" do
84
+ response = justcoin.market_depth(:btcstr)
85
+ expect(response.bids).to eq([
86
+ [bd("226244.0"), bd("0.0702")],
87
+ [bd("225502.26"), bd("0.3")],
88
+ [bd("225500.0"), bd("0.01651")],
89
+ [bd("225392.26"), bd("0.002")]
90
+ ])
91
+ expect(response.asks).to eq([
92
+ [bd("226697.0"), bd("0.88946")],
93
+ [bd("226698.0"), bd("3.3")],
94
+ [bd("226800.0"), bd("0.59715")],
95
+ [bd("226900.0"), bd("1.53781")]
96
+ ])
97
+ end
98
+ end
99
+
100
+ describe '#orders' do
101
+ before do
102
+ stub_get('/orders').with(query: {key: "somekey"}).to_return(fixture("orders.json"))
103
+ end
104
+
105
+ it "returns the user's active orders" do
106
+ response = justcoin.orders
107
+ expect(response.map(&:to_hash)).to eq([
108
+ {'id' => 4054198, 'market' => "BTCSTR", 'type' => "ask", 'price' => bd("229494.0"), 'amount' => bd("0.00436"), 'remaining' => bd("0.00436"), 'matched' => bd("0.0"), 'cancelled' => bd("0.0"), 'createdAt' => t("2014-08-19T10:18:55.582Z")},
109
+ {'id' => 4054182, 'market' => "BTCSTR", 'type' => "bid", 'price' => bd("216777.0"), 'amount' => bd("0.00459"), 'remaining' => bd("0.00459"), 'matched' => bd("0.0"), 'cancelled' => bd("0.0"), 'createdAt' => t("2014-08-19T10:17:55.622Z")}
110
+ ])
111
+ end
112
+ end
113
+
114
+ describe '#order' do
115
+ before do
116
+ stub_get('/orders/3901787').with(query: {key: "somekey"}).to_return(fixture("order.json"))
117
+ end
118
+
119
+ it "returns information about a specific order" do
120
+ response = justcoin.order(3901787)
121
+ expect(response.to_hash).to eq({
122
+ 'id' => 3901787,
123
+ 'createdAt' => t("2014-08-13T09:44:14.093Z"),
124
+ 'market' => "BTCSTR",
125
+ 'type' => "ask",
126
+ 'price' => bd("197999.0"),
127
+ 'original' => bd("0.0803"),
128
+ 'matched' => bd("0.0803"),
129
+ 'canceled' => bd("0.0"),
130
+ 'remaining' => bd("0.0"),
131
+ 'matches' => [
132
+ {'id' => 186158, 'createdAt' => t("2014-08-13T09:44:53.274Z"), 'price' => bd("197999.0"), 'amount' => bd("0.00522")},
133
+ {'id' => 186159, 'createdAt' => t("2014-08-13T09:45:00.747Z"), 'price' => bd("197999.0"), 'amount' => bd("0.07508")}
134
+ ]
135
+ })
136
+ end
137
+ end
138
+
139
+ describe '#create_order' do
140
+ it "accepts only :bid or :ask for the type argument" do
141
+ expect(-> { justcoin.create_order(:btcstr, :foo, 0, 0) }).to raise_error(ArgumentError)
142
+ end
143
+
144
+ it "converts amount and price to string and returns the id of the created order" do
145
+ request = stub_post('/orders').with(
146
+ query: {key: "somekey"},
147
+ body: {
148
+ market: "BTCSTR",
149
+ type: "bid",
150
+ price: "202020.0",
151
+ amount: "0.002462689"
152
+ }
153
+ ).to_return(fixture("create_order.json"))
154
+ response = justcoin.create_order(:btcstr, :bid, 202020, bd("0.002462689"))
155
+ expect(request).to have_been_requested
156
+ expect(response.id).to eq(4089635)
157
+ end
158
+ end
159
+
160
+ describe '#cancel_order' do
161
+ before do
162
+ stub_delete('/orders/4094455').with(query: {key: "somekey"}).to_return(fixture("cancel_order.json"))
163
+ end
164
+
165
+ it "returns true if cancelling was successful" do
166
+ response = justcoin.cancel_order(4094455)
167
+ expect(response).to be(true)
168
+ end
169
+ end
170
+
171
+ end
@@ -0,0 +1,56 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'justcoin'
3
+
4
+ require 'webmock/rspec'
5
+
6
+ RSpec.configure do |config|
7
+ config.include WebMock::API
8
+ end
9
+
10
+ def a_delete(path)
11
+ a_request(:delete, Justcoin::DEFAULT_URL + path)
12
+ end
13
+
14
+ def a_get(path)
15
+ a_request(:get, Justcoin::DEFAULT_URL + path)
16
+ end
17
+
18
+ def a_post(path)
19
+ a_request(:post, Justcoin::DEFAULT_URL + path)
20
+ end
21
+
22
+ def a_put(path)
23
+ a_request(:put, Justcoin::DEFAULT_URL + path)
24
+ end
25
+
26
+ def stub_delete(path)
27
+ stub_request(:delete, Justcoin::DEFAULT_URL + path)
28
+ end
29
+
30
+ def stub_get(path)
31
+ stub_request(:get, Justcoin::DEFAULT_URL + path)
32
+ end
33
+
34
+ def stub_post(path)
35
+ stub_request(:post, Justcoin::DEFAULT_URL + path)
36
+ end
37
+
38
+ def stub_put(path)
39
+ stub_request(:put, Justcoin::DEFAULT_URL + path)
40
+ end
41
+
42
+ def fixture_path
43
+ File.expand_path('../fixtures', __FILE__)
44
+ end
45
+
46
+ def fixture(file)
47
+ File.new(fixture_path + '/' + file)
48
+ end
49
+
50
+ def bd(number)
51
+ BigDecimal.new(number)
52
+ end
53
+
54
+ def t(time_string)
55
+ Time.parse(time_string)
56
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: justcoin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Laszlo Bacsi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
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: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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: hashie
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Justcoin API client
112
+ email:
113
+ - lackac@lackac.hu
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - .rspec
120
+ - .travis.yml
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - justcoin.gemspec
126
+ - lib/justcoin.rb
127
+ - lib/justcoin/body_extractor.rb
128
+ - lib/justcoin/decimal_converter.rb
129
+ - lib/justcoin/version.rb
130
+ - spec/fixtures/balances.json
131
+ - spec/fixtures/cancel_order.json
132
+ - spec/fixtures/create_order.json
133
+ - spec/fixtures/market_depth.json
134
+ - spec/fixtures/markets.json
135
+ - spec/fixtures/order.json
136
+ - spec/fixtures/orders.json
137
+ - spec/justcoin_spec.rb
138
+ - spec/spec_helper.rb
139
+ homepage: https://github.com/lackac/justcoin
140
+ licenses:
141
+ - MIT
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - '>='
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.1.10
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: Justcoin API client
163
+ test_files:
164
+ - spec/fixtures/balances.json
165
+ - spec/fixtures/cancel_order.json
166
+ - spec/fixtures/create_order.json
167
+ - spec/fixtures/market_depth.json
168
+ - spec/fixtures/markets.json
169
+ - spec/fixtures/order.json
170
+ - spec/fixtures/orders.json
171
+ - spec/justcoin_spec.rb
172
+ - spec/spec_helper.rb
173
+ has_rdoc: