bitstamp 0.2.8 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ bitstamp
@@ -0,0 +1 @@
1
+ ruby-1.9.3
data/Gemfile CHANGED
@@ -6,9 +6,8 @@ source "http://rubygems.org"
6
6
  # gem "activesupport", ">= 2.3.5"
7
7
  gem "activemodel", ">= 3.1"
8
8
  gem "activesupport", ">= 3.1"
9
-
10
9
  gem 'curb', '> 0.8.1'
11
-
10
+ gem "ruby-hmac", "0.4.0"
12
11
 
13
12
  # Add dependencies to develop your gem here.
14
13
  # Include everything needed to run rake, tests, features, etc.
@@ -18,3 +17,8 @@ group :development do
18
17
  gem "bundler", "~> 1.3.5"
19
18
  gem "jeweler", "~> 1.8.4"
20
19
  end
20
+
21
+ group :test do
22
+ gem "vcr", "2.6.0"
23
+ gem "webmock", "1.13.0"
24
+ end
@@ -10,8 +10,11 @@ GEM
10
10
  multi_json (~> 1.3)
11
11
  thread_safe (~> 0.1)
12
12
  tzinfo (~> 0.3.33)
13
+ addressable (2.3.5)
13
14
  atomic (1.1.7)
14
15
  builder (3.1.4)
16
+ crack (0.4.1)
17
+ safe_yaml (~> 0.9.0)
15
18
  curb (0.8.3)
16
19
  diff-lcs (1.2.4)
17
20
  git (1.2.5)
@@ -35,9 +38,15 @@ GEM
35
38
  rspec-expectations (2.13.0)
36
39
  diff-lcs (>= 1.1.3, < 2.0)
37
40
  rspec-mocks (2.13.1)
41
+ ruby-hmac (0.4.0)
42
+ safe_yaml (0.9.7)
38
43
  thread_safe (0.1.0)
39
44
  atomic
40
45
  tzinfo (0.3.37)
46
+ vcr (2.6.0)
47
+ webmock (1.13.0)
48
+ addressable (>= 2.2.7)
49
+ crack (>= 0.3.2)
41
50
 
42
51
  PLATFORMS
43
52
  ruby
@@ -50,3 +59,6 @@ DEPENDENCIES
50
59
  jeweler (~> 1.8.4)
51
60
  rdoc (~> 3.12)
52
61
  rspec
62
+ ruby-hmac (= 0.4.0)
63
+ vcr (= 2.6.0)
64
+ webmock (= 1.13.0)
data/README.md CHANGED
@@ -7,17 +7,22 @@ Feel free to fork, modify & redistribute under the MIT license.
7
7
  Add this line to your application's Gemfile:
8
8
 
9
9
  gem 'bitstamp'
10
+
11
+ ## Create API Key
12
+
13
+ More info at: [https://www.bitstamp.net/article/api-key-implementation/](https://www.bitstamp.net/article/api-key-implementation/)
10
14
 
11
15
  ## Setup
12
16
 
13
17
  ```ruby
14
18
  Bitstamp.setup do |config|
15
- config.key = YOUR_BITSTAMP_USERNAME
16
- config.secret = YOUR_BITSTAMP_PASSWORD
19
+ config.key = YOUR_API_KEY
20
+ config.secret = YOUR_API_SECRET
21
+ config.client_id = YOUR_BITSTAMP_USERNAME
17
22
  end
18
23
  ```
19
24
 
20
- If you fail to set your `key` or `secret` a `MissingConfigExecption`
25
+ If you fail to set your `key` or `secret` or `client_id` a `MissingConfigExeception`
21
26
  will be raised.
22
27
 
23
28
  ## Bitstamp ticker
@@ -71,14 +76,12 @@ Bitstamp.user_transactions.all
71
76
 
72
77
  # Tests
73
78
 
74
- If you'd like to run the tests you need to create a yaml file in the
75
- root of the gem `bit_stamp_details.yml` which holds your authentication
76
- details for Bitstamp.
79
+ If you'd like to run the tests you need to set the following environment variables:
77
80
 
78
- ```yaml
79
- bitstamp:
80
- id: 'bitstamp id'
81
- password: 'bitstamp password'
81
+ ```
82
+ export BITSTAMP_KEY=xxx
83
+ export BITSTAMP_SECRET=yyy
84
+ export BITSTAMP_CLIENT_ID=zzz
82
85
  ```
83
86
 
84
87
  ## Contributing
data/Rakefile CHANGED
@@ -25,14 +25,18 @@ Jeweler::Tasks.new do |gem|
25
25
  end
26
26
  Jeweler::RubygemsDotOrgTasks.new
27
27
 
28
- require 'rake/testtask'
29
- Rake::TestTask.new(:test) do |test|
30
- test.libs << 'lib' << 'test'
31
- test.pattern = 'test/**/test_*.rb'
32
- test.verbose = true
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
33
32
  end
34
33
 
35
- task :default => :test
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
36
40
 
37
41
  require 'rdoc/task'
38
42
  Rake::RDocTask.new do |rdoc|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.8
1
+ 0.3.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{bitstamp}
8
- s.version = "0.2.8"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = [%q{Jeffrey Wilcke}]
12
- s.date = %q{2013-08-27}
12
+ s.date = %q{2013-11-19}
13
13
  s.description = %q{Ruby API for use with bitstamp.}
14
14
  s.email = %q{stygeo@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -18,6 +18,8 @@ Gem::Specification.new do |s|
18
18
  ]
19
19
  s.files = [
20
20
  ".rspec",
21
+ ".ruby-gemset",
22
+ ".ruby-version",
21
23
  "Gemfile",
22
24
  "Gemfile.lock",
23
25
  "LICENSE.txt",
@@ -35,8 +37,18 @@ Gem::Specification.new do |s|
35
37
  "lib/bitstamp/transactions.rb",
36
38
  "spec/bitstamp_spec.rb",
37
39
  "spec/collection_spec.rb",
40
+ "spec/fixtures/vcr_cassettes/bitstamp/balance.yml",
41
+ "spec/fixtures/vcr_cassettes/bitstamp/order_book.yml",
42
+ "spec/fixtures/vcr_cassettes/bitstamp/orders/all.yml",
43
+ "spec/fixtures/vcr_cassettes/bitstamp/orders/buy.yml",
44
+ "spec/fixtures/vcr_cassettes/bitstamp/orders/sell/failure.yml",
45
+ "spec/fixtures/vcr_cassettes/bitstamp/ticker.yml",
46
+ "spec/fixtures/vcr_cassettes/bitstamp/transactions.yml",
47
+ "spec/fixtures/vcr_cassettes/bitstamp/user_transactions/all.yml",
38
48
  "spec/orders_spec.rb",
39
49
  "spec/spec_helper.rb",
50
+ "spec/support/bitstamp_setup.rb",
51
+ "spec/support/vcr.rb",
40
52
  "spec/transactions_spec.rb"
41
53
  ]
42
54
  s.homepage = %q{http://github.com/kojnapp/bitstamp}
@@ -52,6 +64,7 @@ Gem::Specification.new do |s|
52
64
  s.add_runtime_dependency(%q<activemodel>, [">= 3.1"])
53
65
  s.add_runtime_dependency(%q<activesupport>, [">= 3.1"])
54
66
  s.add_runtime_dependency(%q<curb>, ["> 0.8.1"])
67
+ s.add_runtime_dependency(%q<ruby-hmac>, ["= 0.4.0"])
55
68
  s.add_development_dependency(%q<rspec>, [">= 0"])
56
69
  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
57
70
  s.add_development_dependency(%q<bundler>, ["~> 1.3.5"])
@@ -60,6 +73,7 @@ Gem::Specification.new do |s|
60
73
  s.add_dependency(%q<activemodel>, [">= 3.1"])
61
74
  s.add_dependency(%q<activesupport>, [">= 3.1"])
62
75
  s.add_dependency(%q<curb>, ["> 0.8.1"])
76
+ s.add_dependency(%q<ruby-hmac>, ["= 0.4.0"])
63
77
  s.add_dependency(%q<rspec>, [">= 0"])
64
78
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
65
79
  s.add_dependency(%q<bundler>, ["~> 1.3.5"])
@@ -69,6 +83,7 @@ Gem::Specification.new do |s|
69
83
  s.add_dependency(%q<activemodel>, [">= 3.1"])
70
84
  s.add_dependency(%q<activesupport>, [">= 3.1"])
71
85
  s.add_dependency(%q<curb>, ["> 0.8.1"])
86
+ s.add_dependency(%q<ruby-hmac>, ["= 0.4.0"])
72
87
  s.add_dependency(%q<rspec>, [">= 0"])
73
88
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
74
89
  s.add_dependency(%q<bundler>, ["~> 1.3.5"])
@@ -2,6 +2,7 @@ require 'active_support/core_ext'
2
2
  require 'active_support/inflector'
3
3
  require 'active_model'
4
4
  require 'curb'
5
+ require 'hmac-sha2'
5
6
 
6
7
  require 'bitstamp/net'
7
8
  require 'bitstamp/helper'
@@ -20,6 +21,9 @@ module Bitstamp
20
21
 
21
22
  # Bitstamp secret
22
23
  mattr_accessor :secret
24
+
25
+ # Bitstamp client ID
26
+ mattr_accessor :client_id
23
27
 
24
28
  # Currency
25
29
  mattr_accessor :currency
@@ -37,6 +41,10 @@ module Bitstamp
37
41
  @@transactions ||= Bitstamp::UserTransactions.new
38
42
  end
39
43
 
44
+ def self.transactions
45
+ return Bitstamp::Transactions.from_api
46
+ end
47
+
40
48
  def self.balance
41
49
  self.sanity_check!
42
50
 
@@ -48,18 +56,22 @@ module Bitstamp
48
56
  end
49
57
 
50
58
  def self.order_book
51
- return JSON.parse Bitstamp::Net.post('/order_book/').body_str
59
+ return JSON.parse Bitstamp::Net.get('/order_book/').body_str
52
60
  end
53
61
 
54
62
  def self.setup
55
63
  yield self
56
64
  end
65
+
66
+ def self.configured?
67
+ self.key && self.secret && self.client_id
68
+ end
57
69
 
58
70
  def self.sanity_check!
59
- unless self.key || self.secret
60
- raise MissingConfigExecption.new("Bitstamp Gem not properly configured")
71
+ unless configured?
72
+ raise MissingConfigExeception.new("Bitstamp Gem not properly configured")
61
73
  end
62
74
  end
63
75
 
64
- class MissingConfigExecption<Exception;end;
76
+ class MissingConfigExeception<Exception;end;
65
77
  end
@@ -9,8 +9,11 @@ module Bitstamp
9
9
 
10
10
  c = Curl::Easy.new(self.to_uri(path))
11
11
 
12
- options[:user] = Bitstamp.key
13
- options[:password] = Bitstamp.secret
12
+ if Bitstamp.configured?
13
+ options[:key] = Bitstamp.key
14
+ options[:nonce] = Time.now.to_i.to_s
15
+ options[:signature] = HMAC::SHA256.hexdigest(Bitstamp.secret, options[:nonce]+Bitstamp.client_id+options[:key]).upcase
16
+ end
14
17
 
15
18
  c.post_body = options.to_query
16
19
 
@@ -22,6 +22,16 @@ module Bitstamp
22
22
  end
23
23
 
24
24
  class UserTransaction < Bitstamp::Model
25
- attr_accessor :datetime, :id, :type, :usd, :btc, :fee, :order_id, :btc_usd
25
+ attr_accessor :datetime, :id, :type, :usd, :btc, :fee, :order_id, :btc_usd, :nonce
26
+ end
27
+
28
+ # adding in methods to pull the last public trades list
29
+ class Transactions < Bitstamp::Model
30
+ attr_accessor :date, :price, :tid, :amount
31
+
32
+ def self.from_api
33
+ Bitstamp::Helper.parse_objects! Bitstamp::Net::get("/transactions").body_str, self
34
+ end
35
+
26
36
  end
27
37
  end
@@ -2,42 +2,56 @@ require 'spec_helper'
2
2
 
3
3
  describe Bitstamp do
4
4
 
5
- it 'should raise if not properly configured' do
6
- -> { Bitstamp.sanity_check! }.should raise_error
7
- end
8
-
9
- it 'should not raise if properly configured' do
10
- Bitstamp.setup do |config|
11
- config.key = 'test'
12
- config.secret = 'test'
5
+ describe :sanity_check! do
6
+ context 'not properly configured' do
7
+ it { -> { Bitstamp.sanity_check! }.should raise_error }
8
+ end
9
+ context 'properly configured' do
10
+ before {
11
+ Bitstamp.setup do |config|
12
+ config.key = 'test'
13
+ config.secret = 'test'
14
+ config.client_id = 'test'
15
+ end
16
+ }
17
+ it { -> { Bitstamp.sanity_check! }.should_not raise_error }
13
18
  end
14
-
15
- -> { Bitstamp.sanity_check! }.should_not raise_error
16
- end
17
-
18
- it 'should have a orders helper method' do
19
- Bitstamp.should respond_to :orders
20
19
  end
21
20
 
22
- it 'should have a ticker helper method' do
23
- Bitstamp.ticker.should be_kind_of Bitstamp::Ticker
21
+ describe :orders do
22
+ it { should respond_to :orders }
24
23
  end
25
24
 
26
- it 'should list information about your balance' do
27
- read_bitstamp_yaml
28
-
29
- Bitstamp.balance.should be_kind_of Hash
25
+ describe :ticket, vcr: {cassette_name: 'bitstamp/ticker'} do
26
+ subject { Bitstamp.ticker }
27
+ it { should be_kind_of Bitstamp::Ticker }
28
+ its(:high) { should == "124.90" }
29
+ its(:last) { should == "124.55" }
30
+ its(:timestamp) { should == "1380237724" }
31
+ its(:bid) { should == "124.55" }
32
+ its(:volume) { should == "7766.46908740" }
33
+ its(:low) { should == "123.00" }
34
+ its(:ask) { should == "124.56" }
30
35
  end
31
36
 
32
- it 'should have a order_book method' do
33
- Bitstamp.order_book.should be_kind_of Hash
37
+ describe :balance, vcr: {cassette_name: 'bitstamp/balance'} do
38
+ context "configured" do
39
+ subject { Bitstamp.balance }
40
+ before { setup_bitstamp }
41
+ it { should == {"btc_reserved"=>"0", "fee"=>"0.4000", "btc_available"=>"0", "usd_reserved"=>"1.02", "btc_balance"=>"0", "usd_balance"=>"6953.07", "usd_available"=>"6952.05"} }
42
+ end
43
+ context "not configured" do
44
+ it { expect { Bitstamp.balance }.to raise_exception(Bitstamp::MissingConfigExeception, "Bitstamp Gem not properly configured") }
45
+ end
34
46
  end
35
47
 
36
- it 'should have bids and asks in the order_book' do
37
- order_book = Bitstamp.order_book
38
- order_book.should have_key("asks")
39
- order_book.should have_key("bids")
40
- order_book["asks"].should be_kind_of Array
41
- order_book["bids"].should be_kind_of Array
48
+ describe :order_book, vcr: {cassette_name: 'bitstamp/order_book'} do
49
+ let(:order_book) { Bitstamp.order_book }
50
+ subject { order_book }
51
+ it { should be_kind_of Hash }
52
+ it { should have_key("asks") }
53
+ it { should have_key("bids") }
54
+ it { order_book["asks"].should be_kind_of Array }
55
+ it { order_book["bids"].should be_kind_of Array }
42
56
  end
43
57
  end
@@ -4,21 +4,9 @@ class Bitstamp::Coin < Bitstamp::Model;end
4
4
  class Bitstamp::Coins < Bitstamp::Collection;end
5
5
 
6
6
  describe Bitstamp::Coins do
7
- let(:kojns) { Bitstamp::Coins.new }
8
-
9
- it 'should have a name representing the class his name but not modules' do
10
- kojns.name.should eq 'coin'
11
- end
12
-
13
- it 'module should reflect a singular form' do
14
- kojns.module.should eq "bitstamp/coin"
15
- end
16
-
17
- it 'should have a model' do
18
- kojns.model.should be Bitstamp::Coin
19
- end
20
-
21
- it 'should have an api end point' do
22
- kojns.path.should eq "/api/coins"
23
- end
7
+ subject { Bitstamp::Coins.new }
8
+ its(:name) { should eq 'coin' }
9
+ its(:module) { should eq "bitstamp/coin" }
10
+ its(:model) { should be Bitstamp::Coin }
11
+ its(:path) { should eq "/api/coins" }
24
12
  end
@@ -0,0 +1,63 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://www.bitstamp.net/api/balance/
6
+ body:
7
+ encoding: US-ASCII
8
+ string: key=BITSTAMP_KEY&nonce=1380237671&signature=67768DD1BBDF45203840CC8688847A2DF5D224CA15B3ABDDC804EA251AC12211
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: !binary |-
14
+ T0s=
15
+ headers:
16
+ !binary "U2VydmVy":
17
+ - !binary |-
18
+ Y2xvdWRmbGFyZS1uZ2lueA==
19
+ !binary "RGF0ZQ==":
20
+ - !binary |-
21
+ VGh1LCAyNiBTZXAgMjAxMyAyMzoyMToxOCBHTVQ=
22
+ !binary "Q29udGVudC1UeXBl":
23
+ - !binary |-
24
+ YXBwbGljYXRpb24vanNvbg==
25
+ !binary "VHJhbnNmZXItRW5jb2Rpbmc=":
26
+ - !binary |-
27
+ Y2h1bmtlZA==
28
+ !binary "Q29ubmVjdGlvbg==":
29
+ - !binary |-
30
+ a2VlcC1hbGl2ZQ==
31
+ !binary "U2V0LUNvb2tpZQ==":
32
+ - !binary |-
33
+ X19jZmR1aWQ9ZDg2ZTkzYTIxNzY5Y2UxZDQzODc2YzQ1N2ZjNTU3ZmNjMTM4
34
+ MDIzNzY3Nzk1ODsgZXhwaXJlcz1Nb24sIDIzLURlYy0yMDE5IDIzOjUwOjAw
35
+ IEdNVDsgcGF0aD0vOyBkb21haW49LmJpdHN0YW1wLm5ldA==
36
+ !binary "Q29udGVudC1MYW5ndWFnZQ==":
37
+ - !binary |-
38
+ ZW4=
39
+ !binary "RXhwaXJlcw==":
40
+ - !binary |-
41
+ VGh1LCAyNiBTZXAgMjAxMyAyMzoyMToxOCBHTVQ=
42
+ !binary "VmFyeQ==":
43
+ - !binary |-
44
+ QWNjZXB0LUxhbmd1YWdl
45
+ !binary "Q2FjaGUtQ29udHJvbA==":
46
+ - !binary |-
47
+ bWF4LWFnZT0w
48
+ !binary "TGFzdC1Nb2RpZmllZA==":
49
+ - !binary |-
50
+ VGh1LCAyNiBTZXAgMjAxMyAyMzoyMToxOCBHTVQ=
51
+ !binary "Q2YtUmF5":
52
+ - !binary |-
53
+ YjQzYjA4ZjM5ZDgwMDk3
54
+ body:
55
+ encoding: ASCII-8BIT
56
+ string: !binary |-
57
+ eyJidGNfcmVzZXJ2ZWQiOiAiMCIsICJmZWUiOiAiMC40MDAwIiwgImJ0Y19h
58
+ dmFpbGFibGUiOiAiMCIsICJ1c2RfcmVzZXJ2ZWQiOiAiMS4wMiIsICJidGNf
59
+ YmFsYW5jZSI6ICIwIiwgInVzZF9iYWxhbmNlIjogIjY5NTMuMDciLCAidXNk
60
+ X2F2YWlsYWJsZSI6ICI2OTUyLjA1In0=
61
+ http_version:
62
+ recorded_at: Thu, 26 Sep 2013 23:21:18 GMT
63
+ recorded_with: VCR 2.6.0