bitstamp-client 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
+ SHA1:
3
+ metadata.gz: 277a98625be62200060a4f297f2f2bc7bb29afa6
4
+ data.tar.gz: 709f85f9b64331d4fee44c47bf9b8273ca52a389
5
+ SHA512:
6
+ metadata.gz: e96ba05efb1ea4eb4b62dff5974060a0cc8bf4e1b118f5f8a3555554f5b3577a184076f1e6366166da5fe6bce6b0c3a5cede411a0e65f03fe62e75d9b8de7ba2
7
+ data.tar.gz: ff6473e3df8d94e583c35dc327e36ae7d7f02863c72c477e7b2ff48a5bff6f2e042e346a91b7c431b93b71f657d59a537375473fb7e1e1ddc215f341a9feaa86
@@ -0,0 +1,13 @@
1
+ module Bitstamp
2
+ module AccountBalance
3
+ def account_balance(nonce: nil, currency_pair: nil)
4
+ params = { nonce: nonce }
5
+
6
+ if currency_pair == nil
7
+ call(request_uri('v2', 'balance'), 'POST', params)
8
+ else
9
+ call(request_uri('v2', 'balance', currency_pair), 'POST', params)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,142 @@
1
+ require 'forwardable'
2
+ require 'json'
3
+ require 'openssl'
4
+ require 'typhoeus'
5
+
6
+ require_relative './account_balance'
7
+ require_relative './deposit'
8
+ require_relative './conversion_rates'
9
+ require_relative './exception'
10
+ require_relative './order_book'
11
+ require_relative './orders'
12
+ require_relative './subaccount_transfer'
13
+ require_relative './ticker'
14
+ require_relative './trading_pairs'
15
+ require_relative './transactions'
16
+ require_relative './user_transactions'
17
+ require_relative './withdrawal'
18
+
19
+ module Bitstamp
20
+ class Client
21
+ extend Forwardable
22
+
23
+ BASE_URI = 'https://www.bitstamp.net/api'
24
+
25
+ def initialize(customer_id:, api_key:, secret:)
26
+ @customer_id = customer_id
27
+ @api_key = api_key
28
+ @secret = secret
29
+
30
+ @connecttimeout = 1
31
+ @timeout = 10
32
+ end
33
+
34
+ class << self
35
+ include ::Bitstamp::ConversionRates
36
+ include ::Bitstamp::OrderBook
37
+ include ::Bitstamp::Ticker
38
+ include ::Bitstamp::TradingPairs
39
+ include ::Bitstamp::Transactions
40
+
41
+ def request_uri(*parts)
42
+ uri = BASE_URI
43
+
44
+ parts.each do |part|
45
+ uri += "/"
46
+ uri += part
47
+ end
48
+
49
+ return uri + "/"
50
+ end
51
+
52
+ def call(request_uri, method, body)
53
+ request_hash = {
54
+ method: method,
55
+ body: body,
56
+ headers: {
57
+ 'User-Agent' => "Bitstamp::Client Ruby v#{::Bitstamp::VERSION}"
58
+ },
59
+ connecttimeout: @connecttimeout,
60
+ timeout: @timeout,
61
+ }
62
+
63
+ request = ::Typhoeus::Request.new(request_uri, request_hash)
64
+ response = request.run
65
+
66
+ return handle_response(response)
67
+ end
68
+
69
+ def handle_response(response)
70
+ body = JSON.parse(response.body)
71
+
72
+ if body.kind_of?(Hash) && body.has_key?('error')
73
+ raise ::Bitstamp::Exception::ServiceError(body)
74
+ end
75
+
76
+ return body
77
+ rescue JSON::ParserError
78
+ raise ::Bitstamp::Exception::InvalidContent.new(response.body)
79
+ end
80
+ end
81
+
82
+ def_delegators "Bitstamp::Client", :request_uri, :handle_response
83
+
84
+ include ::Bitstamp::AccountBalance
85
+ include ::Bitstamp::Deposit
86
+ include ::Bitstamp::Orders
87
+ include ::Bitstamp::SubaccountTransfer
88
+ include ::Bitstamp::UserTransactions
89
+ include ::Bitstamp::Withdrawal
90
+
91
+ def call(request_uri, method, body)
92
+ body = params_with_signature(body)
93
+
94
+ ::Bitstamp::Client.call(request_uri, method, body)
95
+ end
96
+
97
+ def params_with_signature(params = {})
98
+ if params[:nonce] == nil
99
+ params[:nonce] = (Time.now.to_f * 1000000).to_i.to_s # Microseconds
100
+ end
101
+
102
+ params[:key] = @api_key
103
+ params[:signature] = build_signature(params[:nonce])
104
+
105
+ return params
106
+ end
107
+
108
+ def build_signature(nonce)
109
+ message = nonce + @customer_id + @api_key
110
+
111
+ return OpenSSL::HMAC.hexdigest("SHA256", @secret, message).upcase
112
+ end
113
+
114
+ private
115
+
116
+ def run_request(path:, nonce:, request_params: {})
117
+ body = request_params.merge(
118
+ {
119
+ key: key,
120
+ signature: signature(nonce),
121
+ nonce: nonce
122
+ }
123
+ )
124
+
125
+ request_uri = BASE_URI + path
126
+
127
+ request_hash = {
128
+ method: 'POST',
129
+ body: body
130
+ }
131
+
132
+ request = ::Typhoeus::Request.new(request_uri, request_hash)
133
+ response = request.run
134
+ end
135
+
136
+ def signature(nonce)
137
+ message = nonce + @customer_id + @api_key
138
+
139
+ return OpenSSL::HMAC.hexdigest("SHA256", @secret, message)
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,7 @@
1
+ module Bitstamp
2
+ module ConversionRates
3
+ def eur_usd_conversion_rate
4
+ return call(request_uri('eur_usd'), 'GET', nil)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ module Bitstamp
2
+ module Deposit
3
+ def bitcoin_deposit_address(nonce: nil)
4
+ params = { nonce: nonce }
5
+
6
+ call(request_uri('bitcoin_deposit_address'), 'POST', params)
7
+ end
8
+
9
+ def unconfirmed_bitcoin_deposits(nonce: nil)
10
+ params = { nonce: nonce }
11
+
12
+ call(request_uri('unconfirmed_btc'), 'POST', params)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ module Bitstamp
2
+ module Exception
3
+ class ServiceError < StandardError
4
+ attr_reader :body
5
+
6
+ def initialize(body)
7
+ @body = body
8
+ end
9
+
10
+ def message
11
+ @body.fetch('error')
12
+ end
13
+
14
+ alias_method :to_s, :message
15
+ end
16
+
17
+ class InvalidContent < StandardError
18
+ attr_reader :body
19
+
20
+ def initialize(body)
21
+ @body = body
22
+ end
23
+
24
+ def message
25
+ "Failed to parse body as 'json': '#{@body}'"
26
+ end
27
+
28
+ def inspect
29
+ "#{self.class.name}: #{message}"
30
+ end
31
+
32
+ alias_method :to_s, :message
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ module Bitstamp
2
+ module OrderBook
3
+ def order_book(currency_pair: nil)
4
+ if currency_pair == nil
5
+ return call(request_uri('order_book'), 'GET', nil)
6
+ else
7
+ return call(request_uri('v2', 'order_book', currency_pair), 'GET', nil)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,71 @@
1
+ module Bitstamp
2
+ module Orders
3
+ def open_orders(nonce: nil, currency_pair: nil)
4
+ params = { nonce: nonce }
5
+
6
+ if currency_pair == nil
7
+ call(request_uri('v2', 'open_orders', 'all'), 'POST', params)
8
+ else
9
+ call(request_uri('v2', 'open_orders', currency_pair), 'POST', params)
10
+ end
11
+ end
12
+
13
+ def order_status(nonce: nil, id:)
14
+ params = { nonce: nonce, id: id }
15
+
16
+ call(request_uri('v2', 'order_status'), 'POST', params)
17
+ end
18
+
19
+ def cancel_order(nonce: nil, id:)
20
+ params = { nonce: nonce, id: id }
21
+
22
+ call(request_uri('v2', 'cancel_order'), 'POST', params)
23
+ end
24
+
25
+ def cancel_all_orders(nonce: nil)
26
+ params = { nonce: nonce }
27
+
28
+ call(request_uri('cancel_all_orders'), 'POST', params)
29
+ end
30
+
31
+ def buy_limit_order(nonce: nil, amount:, price:, limit_price:, currency_pair:)
32
+ params = {
33
+ nonce: nonce,
34
+ amount: amount,
35
+ price: price,
36
+ limit_price: limit_price
37
+ }
38
+
39
+ call(request_uri('v2', 'buy', currency_pair), 'POST', params)
40
+ end
41
+
42
+ def buy_market_order(nonce: nil, amount:)
43
+ params = {
44
+ nonce: nonce,
45
+ amount: amount,
46
+ }
47
+
48
+ call(request_uri('v2', 'buy', 'market', currency_pair), 'POST', params)
49
+ end
50
+
51
+ def sell_limit_order(nonce: nil, amount:, price:, limit_price:, currency_pair:)
52
+ params = {
53
+ nonce: nonce,
54
+ amount: amount,
55
+ price: price,
56
+ limit_price: limit_price
57
+ }
58
+
59
+ call(request_uri('v2', 'sell', currency_pair), 'POST', params)
60
+ end
61
+
62
+ def sell_market_order(nonce: nil, amount:)
63
+ params = {
64
+ nonce: nonce,
65
+ amount: amount,
66
+ }
67
+
68
+ call(request_uri('v2', 'sell', 'market', currency_pair), 'POST', params)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,25 @@
1
+ module Bitstamp
2
+ module SubaccountTransfer
3
+ def transfer_to_main(nonce: nil, amount:, currency:, sub_account:)
4
+ params = {
5
+ nonce: nonce,
6
+ amount: amount,
7
+ currency: currency,
8
+ subAccount: sub_account
9
+ }
10
+
11
+ call(request_uri('v2', 'transfer-to-main'), 'POST', params)
12
+ end
13
+
14
+ def transfer_from_main(nonce: nil, amount:, currency:, sub_account:)
15
+ params = {
16
+ nonce: nonce,
17
+ amount: amount,
18
+ currency: currency,
19
+ subAccount: sub_account
20
+ }
21
+
22
+ call(request_uri('v2', 'transfer-from-main'), 'POST', params)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ module Bitstamp
2
+ module Ticker
3
+ def ticker(currency_pair: nil)
4
+ if currency_pair == nil
5
+ return call(request_uri('ticker'), 'GET', nil)
6
+ else
7
+ return call(request_uri('v2', 'ticker', currency_pair), 'GET', nil)
8
+ end
9
+ end
10
+
11
+ def hourly_ticker(currency_pair: nil)
12
+ if currency_pair == nil
13
+ return call(request_uri('ticker_hour'), 'GET', nil)
14
+ else
15
+ return call(request_uri('v2', 'ticker_hour', currency_pair), 'GET', nil)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ module Bitstamp
2
+ module TradingPairs
3
+ def trading_pair_info
4
+ return call(request_uri('v2', 'trading-pair-info'), 'GET', nil)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module Bitstamp
2
+ module Transactions
3
+ def transactions(currency_pair: nil)
4
+ if currency_pair == nil
5
+ return call(request_uri('transactions'), 'GET', nil)
6
+ else
7
+ return call(request_uri('v2', 'transactions', currency_pair, ''), 'GET', nil)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Bitstamp
2
+ module UserTransactions
3
+ def user_transactions(nonce: nil, offset: 0, limit: 100, sort: 'desc', currency_pair: nil)
4
+ params = { nonce: nonce }
5
+
6
+ if currency_pair == nil
7
+ call(request_uri('v2', 'user_transactions'), 'POST', params)
8
+ else
9
+ call(request_uri('v2', 'user_transactions', currency_pair), 'POST', params)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Bitstamp
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,19 @@
1
+ module Bitstamp
2
+ module Withdrawal
3
+ def withdrawal_requests(nonce: nil, timedelta: 86400)
4
+ params = { nonce: nonce, timedelta: timedelta }
5
+
6
+ call(request_uri('v2', 'withdrawal-requests'), 'POST', params)
7
+ end
8
+
9
+ def bitcoin_withdrawal(nonce: nil, amount:, address:)
10
+ params = {
11
+ nonce: nonce,
12
+ amount: amount,
13
+ address: address,
14
+ }
15
+
16
+ call(request_uri('bitcoin_withdrawal'), 'POST', params)
17
+ end
18
+ end
19
+ end
data/lib/bitstamp.rb ADDED
@@ -0,0 +1,2 @@
1
+ require_relative './bitstamp/version'
2
+ require_relative './bitstamp/client'
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bitstamp-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tobias Schoknecht
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '12.3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 12.3.0
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '12.3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 12.3.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.7'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 3.7.0
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '3.7'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 3.7.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: builder
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.2'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 3.2.3
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.2'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 3.2.3
73
+ - !ruby/object:Gem::Dependency
74
+ name: rack-test
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: 0.8.2
80
+ type: :development
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: 0.8.2
87
+ - !ruby/object:Gem::Dependency
88
+ name: typhoeus
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "~>"
92
+ - !ruby/object:Gem::Version
93
+ version: '1.3'
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 1.3.0
97
+ type: :runtime
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.3'
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 1.3.0
107
+ description: Bitstamp Exchange API Client
108
+ email:
109
+ - tobias.schoknecht@gmail.com
110
+ executables: []
111
+ extensions: []
112
+ extra_rdoc_files: []
113
+ files:
114
+ - lib/bitstamp.rb
115
+ - lib/bitstamp/account_balance.rb
116
+ - lib/bitstamp/client.rb
117
+ - lib/bitstamp/conversion_rates.rb
118
+ - lib/bitstamp/deposit.rb
119
+ - lib/bitstamp/exception.rb
120
+ - lib/bitstamp/order_book.rb
121
+ - lib/bitstamp/orders.rb
122
+ - lib/bitstamp/subaccount_transfer.rb
123
+ - lib/bitstamp/ticker.rb
124
+ - lib/bitstamp/trading_pairs.rb
125
+ - lib/bitstamp/transactions.rb
126
+ - lib/bitstamp/user_transactions.rb
127
+ - lib/bitstamp/version.rb
128
+ - lib/bitstamp/withdrawal.rb
129
+ homepage: https://github.com/tobischo/bitstamp
130
+ licenses:
131
+ - MIT
132
+ metadata: {}
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 2.6.14
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: Very generic client for REST API with basic error handling
153
+ test_files: []