justcoin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: