bitstamper 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 +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +15 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +66 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +6 -0
- data/bin/console +32 -0
- data/bin/setup +8 -0
- data/bin/websocket +55 -0
- data/bitstamper.gemspec +35 -0
- data/credentials.yml.example +9 -0
- data/lib/.DS_Store +0 -0
- data/lib/bitstamper/configuration.rb +41 -0
- data/lib/bitstamper/constants.rb +34 -0
- data/lib/bitstamper/errors.rb +11 -0
- data/lib/bitstamper/extensions/hash.rb +27 -0
- data/lib/bitstamper/models/balance.rb +56 -0
- data/lib/bitstamper/models/base.rb +11 -0
- data/lib/bitstamper/models/deposit.rb +26 -0
- data/lib/bitstamper/models/live_trade.rb +41 -0
- data/lib/bitstamper/models/order.rb +48 -0
- data/lib/bitstamper/models/order_book.rb +28 -0
- data/lib/bitstamper/models/ticker.rb +33 -0
- data/lib/bitstamper/models/trading_pair.rb +35 -0
- data/lib/bitstamper/models/transaction.rb +37 -0
- data/lib/bitstamper/models/user_transaction.rb +55 -0
- data/lib/bitstamper/models/withdrawal.rb +53 -0
- data/lib/bitstamper/rest/client.rb +102 -0
- data/lib/bitstamper/rest/errors.rb +39 -0
- data/lib/bitstamper/rest/private/balances.rb +18 -0
- data/lib/bitstamper/rest/private/deposits.rb +51 -0
- data/lib/bitstamper/rest/private/orders.rb +103 -0
- data/lib/bitstamper/rest/private/transactions.rb +19 -0
- data/lib/bitstamper/rest/private/withdrawals.rb +53 -0
- data/lib/bitstamper/rest/public/currencies.rb +14 -0
- data/lib/bitstamper/rest/public/order_book.rb +14 -0
- data/lib/bitstamper/rest/public/ticker.rb +30 -0
- data/lib/bitstamper/rest/public/trading_pairs.rb +14 -0
- data/lib/bitstamper/rest/public/transactions.rb +18 -0
- data/lib/bitstamper/utilities.rb +61 -0
- data/lib/bitstamper/version.rb +3 -0
- data/lib/bitstamper/websocket/client.rb +127 -0
- data/lib/bitstamper.rb +72 -0
- metadata +231 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Models
|
3
|
+
class Order < Base
|
4
|
+
attr_accessor :id, :currency_pair, :type, :order_type, :price, :amount, :datetime
|
5
|
+
attr_accessor :event, :error, :message
|
6
|
+
|
7
|
+
BUY = 0
|
8
|
+
SELL = 1
|
9
|
+
|
10
|
+
MAPPING = {
|
11
|
+
"id" => :string,
|
12
|
+
"currency_pair" => :string,
|
13
|
+
"type" => :integer,
|
14
|
+
"price" => :float,
|
15
|
+
"amount" => :float,
|
16
|
+
"event" => :string
|
17
|
+
}
|
18
|
+
|
19
|
+
def initialize(hash)
|
20
|
+
hash["type"] = hash["order_type"] if hash.fetch("type", nil).to_s.empty? && hash.has_key?("order_type")
|
21
|
+
|
22
|
+
hash.each do |key, value|
|
23
|
+
type = ::Bitstamper::Models::Order::MAPPING.fetch(key, nil)
|
24
|
+
value = value && type ? ::Bitstamper::Utilities::convert_value(value, type) : value
|
25
|
+
self.send("#{key}=", value) if self.respond_to?(key)
|
26
|
+
end
|
27
|
+
|
28
|
+
datetime = hash.fetch("datetime", nil)&.to_s
|
29
|
+
|
30
|
+
if !datetime.to_s.empty? && datetime.include?("-")
|
31
|
+
self.datetime = ::Bitstamper::Utilities::convert_value(datetime, :datetime)
|
32
|
+
elsif !datetime.to_s.empty? && ::Bitstamper::Utilities.numeric?(datetime)
|
33
|
+
self.datetime = ::Bitstamper::Utilities::convert_value(datetime, :time)
|
34
|
+
end
|
35
|
+
|
36
|
+
self.order_type = case self.type
|
37
|
+
when ::Bitstamper::Models::Order::BUY then :buy
|
38
|
+
when ::Bitstamper::Models::Order::SELL then :sell
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.parse(data)
|
43
|
+
data&.collect { |item| ::Bitstamper::Models::Order.new(item) }
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Models
|
3
|
+
class OrderBook
|
4
|
+
attr_accessor :timestamp, :bids, :asks
|
5
|
+
|
6
|
+
def initialize(hash)
|
7
|
+
self.bids = []
|
8
|
+
self.asks = []
|
9
|
+
|
10
|
+
self.timestamp = ::Bitstamper::Utilities.epoch_to_time(hash.fetch("timestamp", nil)) if hash.has_key?("timestamp") && !hash.fetch("timestamp", nil).to_s.empty?
|
11
|
+
|
12
|
+
process(hash)
|
13
|
+
end
|
14
|
+
|
15
|
+
def process(hash)
|
16
|
+
[:bids, :asks].each do |type|
|
17
|
+
hash.fetch(type.to_s, []).each do |item|
|
18
|
+
price = item&.first&.to_f
|
19
|
+
quantity = item&.last&.to_f
|
20
|
+
value = !price.nil? && !quantity.nil? ? price * quantity : nil
|
21
|
+
self.send(type).send(:<<, {price: price, quantity: quantity, value: value})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Models
|
3
|
+
class Ticker < Base
|
4
|
+
attr_accessor :last, :high, :low, :volume, :bid, :ask, :timestamp, :vwap, :open, :currency_pair
|
5
|
+
|
6
|
+
MAPPING = {
|
7
|
+
"high" => :float,
|
8
|
+
"last" => :float,
|
9
|
+
"timestamp" => :time,
|
10
|
+
"bid" => :float,
|
11
|
+
"vwap" => :float,
|
12
|
+
"volume" => :float,
|
13
|
+
"low" => :float,
|
14
|
+
"ask" => :float,
|
15
|
+
"open" => :float,
|
16
|
+
"currency_pair" => :string,
|
17
|
+
}
|
18
|
+
|
19
|
+
def initialize(hash)
|
20
|
+
hash.each do |key, value|
|
21
|
+
type = ::Bitstamper::Models::Ticker::MAPPING.fetch(key, nil)
|
22
|
+
value = value && type ? ::Bitstamper::Utilities::convert_value(value, type) : value
|
23
|
+
self.send("#{key}=", value) if self.respond_to?(key)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.parse(data)
|
28
|
+
data&.collect { |item| ::Bitstamper::Models::Ticker.new(item) }
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Models
|
3
|
+
class TradingPair < Base
|
4
|
+
attr_accessor :name, :url_symbol, :description
|
5
|
+
attr_accessor :base_decimals, :counter_decimals, :minimum_order, :trading
|
6
|
+
|
7
|
+
MAPPING = {
|
8
|
+
"name" => :string,
|
9
|
+
"url_symbol" => :string,
|
10
|
+
"description" => :string,
|
11
|
+
"base_decimals" => :integer,
|
12
|
+
"counter_decimals" => :integer,
|
13
|
+
"minimum_order" => :string,
|
14
|
+
"trading" => :string,
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize(hash)
|
18
|
+
hash.each do |key, value|
|
19
|
+
type = ::Bitstamper::Models::TradingPair::MAPPING.fetch(key, nil)
|
20
|
+
value = value && type ? ::Bitstamper::Utilities::convert_value(value, type) : value
|
21
|
+
self.send("#{key}=", value) if self.respond_to?(key)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def enabled?
|
26
|
+
self.trading.downcase.strip.eql?("enabled")
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.parse(data)
|
30
|
+
data&.collect { |item| ::Bitstamper::Models::TradingPair.new(item) }
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Models
|
3
|
+
class Transaction < Base
|
4
|
+
attr_accessor :id, :type, :transaction_type, :date, :price, :amount
|
5
|
+
|
6
|
+
TYPES = {
|
7
|
+
0 => :buy,
|
8
|
+
1 => :sell
|
9
|
+
}
|
10
|
+
|
11
|
+
MAPPING = {
|
12
|
+
"id" => :string,
|
13
|
+
"type" => :integer,
|
14
|
+
"date" => :time,
|
15
|
+
"price" => :float,
|
16
|
+
"amount" => :float,
|
17
|
+
}
|
18
|
+
|
19
|
+
def initialize(hash)
|
20
|
+
hash.each do |key, value|
|
21
|
+
type = ::Bitstamper::Models::Transaction::MAPPING.fetch(key, nil)
|
22
|
+
value = value && type ? ::Bitstamper::Utilities::convert_value(value, type) : value
|
23
|
+
self.send("#{key}=", value) if self.respond_to?(key)
|
24
|
+
end
|
25
|
+
|
26
|
+
self.id = hash.fetch("id", hash.fetch("tid", nil))&.to_s
|
27
|
+
|
28
|
+
self.transaction_type = TYPES[self.type]
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.parse(data)
|
32
|
+
data&.collect { |item| ::Bitstamper::Models::Transaction.new(item) }
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Models
|
3
|
+
class UserTransaction < Base
|
4
|
+
attr_accessor :id, :order_id, :type, :transaction_type, :datetime, :fee
|
5
|
+
attr_accessor :usd, :eur
|
6
|
+
attr_accessor :btc, :btc_usd, :btc_eur
|
7
|
+
attr_accessor :eth, :eth_btc, :eth_usd, :eth_eur
|
8
|
+
attr_accessor :ltc, :xrp, :bch
|
9
|
+
|
10
|
+
TYPES = {
|
11
|
+
0 => :deposit,
|
12
|
+
1 => :withdrawal,
|
13
|
+
2 => :market_trade,
|
14
|
+
14 => :sub_account_transfer
|
15
|
+
}
|
16
|
+
|
17
|
+
MAPPING = {
|
18
|
+
"id" => :string,
|
19
|
+
"order_id" => :string,
|
20
|
+
"type" => :integer,
|
21
|
+
"datetime" => :datetime,
|
22
|
+
"fee" => :float,
|
23
|
+
"usd" => :float,
|
24
|
+
"eur" => :float,
|
25
|
+
"btc" => :float,
|
26
|
+
"btc_usd" => :float,
|
27
|
+
"btc_eur" => :float,
|
28
|
+
"eth" => :float,
|
29
|
+
"eth_btc" => :float,
|
30
|
+
"eth_usd" => :float,
|
31
|
+
"eth_eur" => :float,
|
32
|
+
"ltc" => :float,
|
33
|
+
"xrp" => :float,
|
34
|
+
"bch" => :float,
|
35
|
+
}
|
36
|
+
|
37
|
+
def initialize(hash)
|
38
|
+
hash.each do |key, value|
|
39
|
+
type = ::Bitstamper::Models::UserTransaction::MAPPING.fetch(key, nil)
|
40
|
+
value = value && type ? ::Bitstamper::Utilities::convert_value(value, type) : value
|
41
|
+
self.send("#{key}=", value) if self.respond_to?(key)
|
42
|
+
end
|
43
|
+
|
44
|
+
self.id = hash.fetch("id", hash.fetch("tid", nil))&.to_s
|
45
|
+
|
46
|
+
self.transaction_type = TYPES[self.type]
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.parse(data)
|
50
|
+
data&.collect { |item| ::Bitstamper::Models::UserTransaction.new(item) }
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Models
|
3
|
+
class Withdrawal < Base
|
4
|
+
attr_accessor :id, :currency, :amount, :datetime
|
5
|
+
attr_accessor :type, :status
|
6
|
+
attr_accessor :address, :transaction_id
|
7
|
+
|
8
|
+
TYPES = {
|
9
|
+
0 => :sepa,
|
10
|
+
1 => :bitcoin,
|
11
|
+
2 => :wire,
|
12
|
+
14 => :xrp,
|
13
|
+
15 => :ltc,
|
14
|
+
16 => :eth
|
15
|
+
}
|
16
|
+
|
17
|
+
STATUS = {
|
18
|
+
0 => :open,
|
19
|
+
1 => :in_process,
|
20
|
+
2 => :finished,
|
21
|
+
3 => :cancelled,
|
22
|
+
4 => :failed
|
23
|
+
}
|
24
|
+
|
25
|
+
MAPPING = {
|
26
|
+
"id" => :string,
|
27
|
+
"currency" => :string,
|
28
|
+
"amount" => :float,
|
29
|
+
"datetime" => :datetime,
|
30
|
+
"type" => :integer,
|
31
|
+
"status" => :integer,
|
32
|
+
"address" => :string,
|
33
|
+
"transaction_id" => :string
|
34
|
+
}
|
35
|
+
|
36
|
+
def initialize(hash)
|
37
|
+
hash.each do |key, value|
|
38
|
+
type = ::Bitstamper::Models::Withdrawal::MAPPING.fetch(key, nil)
|
39
|
+
value = value && type ? ::Bitstamper::Utilities::convert_value(value, type) : value
|
40
|
+
self.send("#{key}=", value) if self.respond_to?(key)
|
41
|
+
end
|
42
|
+
|
43
|
+
self.type = TYPES[self.type]
|
44
|
+
self.status = STATUS[self.status]
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.parse(data)
|
48
|
+
data&.collect { |item| ::Bitstamper::Models::Withdrawal.new(item) }
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Rest
|
3
|
+
class Client
|
4
|
+
attr_accessor :url, :configuration
|
5
|
+
|
6
|
+
def initialize(configuration: ::Bitstamper.configuration)
|
7
|
+
self.url = "https://www.bitstamp.net/api"
|
8
|
+
self.configuration = configuration
|
9
|
+
end
|
10
|
+
|
11
|
+
include ::Bitstamper::Rest::Errors
|
12
|
+
|
13
|
+
include ::Bitstamper::Rest::Public::Ticker
|
14
|
+
include ::Bitstamper::Rest::Public::OrderBook
|
15
|
+
include ::Bitstamper::Rest::Public::Transactions
|
16
|
+
include ::Bitstamper::Rest::Public::TradingPairs
|
17
|
+
include ::Bitstamper::Rest::Public::Currencies
|
18
|
+
|
19
|
+
include ::Bitstamper::Rest::Private::Balances
|
20
|
+
include ::Bitstamper::Rest::Private::Deposits
|
21
|
+
include ::Bitstamper::Rest::Private::Withdrawals
|
22
|
+
include ::Bitstamper::Rest::Private::Orders
|
23
|
+
include ::Bitstamper::Rest::Private::Transactions
|
24
|
+
|
25
|
+
def configured?
|
26
|
+
!self.configuration.key.to_s.empty? && !self.configuration.secret.to_s.empty? && !self.configuration.client_id.to_s.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_credentials!
|
30
|
+
unless configured?
|
31
|
+
raise ::Bitstamper::Errors::MissingConfigError.new("Bitstamp Gem not properly configured")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def path_with_currency_pair(path, currency_pair)
|
36
|
+
path += "/#{::Bitstamper::Utilities.fix_currency_pair(currency_pair)}" if !currency_pair.to_s.empty?
|
37
|
+
return path
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_uri(path)
|
41
|
+
"#{self.url}#{path}/"
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse(response)
|
45
|
+
error?(response)
|
46
|
+
response
|
47
|
+
end
|
48
|
+
|
49
|
+
def get(path, params: {}, options: {})
|
50
|
+
request path, method: :get, options: options
|
51
|
+
end
|
52
|
+
|
53
|
+
def post(path, params: {}, data: {}, options: {})
|
54
|
+
request path, method: :post, params: params, data: data.merge(auth), options: options
|
55
|
+
end
|
56
|
+
|
57
|
+
def auth(data = {})
|
58
|
+
if configured?
|
59
|
+
data[:key] = self.configuration.key
|
60
|
+
data[:nonce] = (Time.now.to_f * 1_000_000_000).to_i.to_s
|
61
|
+
message = data[:nonce] + self.configuration.client_id.to_s + data[:key]
|
62
|
+
data[:signature] = HMAC::SHA256.hexdigest(self.configuration.secret, message).upcase
|
63
|
+
end
|
64
|
+
|
65
|
+
return data
|
66
|
+
end
|
67
|
+
|
68
|
+
def request(path, method: :get, params: {}, data: {}, options: {})
|
69
|
+
user_agent = options.fetch(:user_agent, self.configuration.faraday.fetch(:user_agent, nil))
|
70
|
+
proxy = options.fetch(:proxy, nil)
|
71
|
+
|
72
|
+
connection = Faraday.new(url: to_uri(path)) do |builder|
|
73
|
+
builder.headers[:user_agent] = user_agent if !user_agent.to_s.empty?
|
74
|
+
builder.request :url_encoded if method.eql?(:post)
|
75
|
+
builder.response :logger if self.configuration.verbose_faraday?
|
76
|
+
builder.response :json
|
77
|
+
|
78
|
+
if proxy
|
79
|
+
puts "[Bitstamper::Rest::Client] - Will connect to Bitstamp using proxy: #{proxy.inspect}" if self.configuration.verbose_faraday?
|
80
|
+
builder.proxy = proxy
|
81
|
+
end
|
82
|
+
|
83
|
+
builder.adapter self.configuration.faraday.fetch(:adapter, :net_http)
|
84
|
+
end
|
85
|
+
|
86
|
+
case method
|
87
|
+
when :get
|
88
|
+
connection.get do |request|
|
89
|
+
request.params = params if params && !params.empty?
|
90
|
+
end&.body
|
91
|
+
when :post
|
92
|
+
connection.post do |request|
|
93
|
+
request.body = data
|
94
|
+
request.params = params if params && !params.empty?
|
95
|
+
end&.body
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Rest
|
3
|
+
module Errors
|
4
|
+
|
5
|
+
def error?(response)
|
6
|
+
if response.is_a?(Hash)
|
7
|
+
if response.has_key?("error")
|
8
|
+
process_error(response.fetch("error", nil))
|
9
|
+
elsif response.fetch("status", nil) == "error"
|
10
|
+
process_error(response.fetch("reason", nil))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def process_error(error)
|
16
|
+
if error.is_a?(String)
|
17
|
+
if error == ::Bitstamper::Constants::ERRORS[:matches][:invalid_permissions]
|
18
|
+
raise ::Bitstamper::Errors::InvalidPermissionsError.new(::Bitstamper::Constants::ERRORS[:responses][:invalid_permissions])
|
19
|
+
elsif error == ::Bitstamper::Constants::ERRORS[:matches][:invalid_order]
|
20
|
+
raise ::Bitstamper::Errors::InvalidOrderError.new(::Bitstamper::Constants::ERRORS[:matches][:invalid_order])
|
21
|
+
end
|
22
|
+
elsif error.is_a?(Hash)
|
23
|
+
process_hash_error(error)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def process_hash_error(error)
|
28
|
+
if error.has_key?("amount")
|
29
|
+
raise ::Bitstamper::Errors::InvalidAmountError.new(error.fetch("amount", [])&.first)
|
30
|
+
elsif error.has_key?("address")
|
31
|
+
raise ::Bitstamper::Errors::InvalidAddressError.new(error.fetch("address", [])&.first)
|
32
|
+
elsif error.has_key?("__all__")
|
33
|
+
raise ::Bitstamper::Errors::InvalidOrderError.new(error.fetch("__all__", [])&.first)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Rest
|
3
|
+
module Private
|
4
|
+
module Balances
|
5
|
+
|
6
|
+
def balance(currency_pair: nil)
|
7
|
+
check_credentials!
|
8
|
+
|
9
|
+
path = path_with_currency_pair("/v2/balance", currency_pair)
|
10
|
+
response = post(path)
|
11
|
+
|
12
|
+
::Bitstamper::Models::Balance.parse(response) if response
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Rest
|
3
|
+
module Private
|
4
|
+
module Deposits
|
5
|
+
|
6
|
+
def btc_deposit_address
|
7
|
+
deposit_address("btc")
|
8
|
+
end
|
9
|
+
|
10
|
+
def eth_deposit_address
|
11
|
+
deposit_address("eth")
|
12
|
+
end
|
13
|
+
|
14
|
+
def xrp_deposit_address
|
15
|
+
deposit_address("xrp")
|
16
|
+
end
|
17
|
+
|
18
|
+
def bch_deposit_address
|
19
|
+
deposit_address("bch")
|
20
|
+
end
|
21
|
+
|
22
|
+
def ltc_deposit_address
|
23
|
+
deposit_address("ltc")
|
24
|
+
end
|
25
|
+
|
26
|
+
def deposit_address(currency)
|
27
|
+
check_credentials!
|
28
|
+
|
29
|
+
currency = currency.to_s.downcase
|
30
|
+
|
31
|
+
if !::Bitstamper::Constants::AVAILABLE_CRYPTOS.include?(currency)
|
32
|
+
raise ::Bitstamper::Errors::InvalidCurrencyError.new("#{currency} is not a tradeable crypto currency on Bitstamp.")
|
33
|
+
end
|
34
|
+
|
35
|
+
path = currency.eql?("btc") ? "/bitcoin_deposit_address" : "/v2/#{currency}_address"
|
36
|
+
response = post(path)
|
37
|
+
response = response.is_a?(String) ? {"address" => response} : response
|
38
|
+
|
39
|
+
return response
|
40
|
+
end
|
41
|
+
|
42
|
+
def unconfirmed_bitcoins
|
43
|
+
check_credentials!
|
44
|
+
response = post("/unconfirmed_btc")
|
45
|
+
Bitstamper::Models::Deposit.parse(response) if response
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Rest
|
3
|
+
module Private
|
4
|
+
module Orders
|
5
|
+
|
6
|
+
def open_orders(currency_pair = nil)
|
7
|
+
path = !currency_pair.to_s.empty? ? "/v2/open_orders/#{::Bitstamper::Utilities.fix_currency_pair(currency_pair)}" : "/v2/open_orders/all"
|
8
|
+
response = post(path)
|
9
|
+
Bitstamper::Models::Order.parse(response) if response
|
10
|
+
end
|
11
|
+
|
12
|
+
def find_open_order(order_id)
|
13
|
+
open_orders.select { |order| order.id == order_id }&.first
|
14
|
+
end
|
15
|
+
|
16
|
+
# https://www.bitstamp.net/api/#buy-order
|
17
|
+
def buy(currency_pair: "btcusd", amount:, price:, limit_price: nil, daily_order: nil)
|
18
|
+
create_order(
|
19
|
+
currency_pair: currency_pair,
|
20
|
+
direction: Bitstamper::Constants::BUY_ORDER,
|
21
|
+
amount: amount,
|
22
|
+
price: price,
|
23
|
+
limit_price: limit_price,
|
24
|
+
daily_order: daily_order
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
# https://www.bitstamp.net/api/#sell-order
|
29
|
+
def sell(currency_pair: "btcusd", amount:, price:, limit_price: nil, daily_order: nil)
|
30
|
+
create_order(
|
31
|
+
currency_pair: currency_pair,
|
32
|
+
direction: Bitstamper::Constants::SELL_ORDER,
|
33
|
+
amount: amount,
|
34
|
+
price: price,
|
35
|
+
limit_price: limit_price,
|
36
|
+
daily_order: daily_order
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Request parameters
|
41
|
+
# [AUTH]
|
42
|
+
# amount - Amount.
|
43
|
+
# price - Price.
|
44
|
+
# limit_price - If the order gets executed, a new sell order will be placed, with "limit_price" as its price.
|
45
|
+
# daily_order - (Optional): Opens buy limit order which will be canceled at 0:00 UTC unless it already has been executed. Possible value: True
|
46
|
+
def create_order(currency_pair: "btcusd", direction: Bitstamper::Constants::BUY_ORDER, amount:, price:, limit_price: nil, daily_order: nil)
|
47
|
+
currency_pair = ::Bitstamper::Utilities.fix_currency_pair(currency_pair)
|
48
|
+
direction = fix_order_direction(direction)
|
49
|
+
|
50
|
+
path = case direction
|
51
|
+
when Bitstamper::Constants::BUY_ORDER
|
52
|
+
"/v2/buy/#{currency_pair}"
|
53
|
+
when Bitstamper::Constants::SELL_ORDER
|
54
|
+
"/v2/sell/#{currency_pair}"
|
55
|
+
end
|
56
|
+
|
57
|
+
data = {
|
58
|
+
amount: amount,
|
59
|
+
price: price
|
60
|
+
}
|
61
|
+
|
62
|
+
data[:limit_price] = limit_price if !limit_price.nil?
|
63
|
+
data[:daily_order] = true if daily_order == true
|
64
|
+
|
65
|
+
response = parse(post(path, data: data))
|
66
|
+
|
67
|
+
Bitstamper::Models::Order.new(response.merge("currency_pair" => currency_pair)) if response
|
68
|
+
end
|
69
|
+
|
70
|
+
def fix_order_direction(direction)
|
71
|
+
if direction.is_a?(Symbol)
|
72
|
+
direction = case direction
|
73
|
+
when :buy
|
74
|
+
Bitstamper::Constants::BUY_ORDER
|
75
|
+
when :sell
|
76
|
+
Bitstamper::Constants::SELL_ORDER
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
return direction
|
81
|
+
end
|
82
|
+
|
83
|
+
def order_status(order_id)
|
84
|
+
response = post("/order_status", data: {id: order_id})
|
85
|
+
status = response&.fetch("status", nil)
|
86
|
+
transactions = Bitstamper::Models::UserTransaction.parse(response&.fetch("transactions", []))
|
87
|
+
|
88
|
+
return {status: status, transactions: transactions}
|
89
|
+
end
|
90
|
+
|
91
|
+
def cancel_all_orders!
|
92
|
+
parse(post('/cancel_all_orders'))
|
93
|
+
end
|
94
|
+
|
95
|
+
def cancel_order!(order_id)
|
96
|
+
response = parse(post('/v2/cancel_order', data: {id: order_id}))
|
97
|
+
Bitstamper::Models::Order.new(response) if response
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Rest
|
3
|
+
module Private
|
4
|
+
module Transactions
|
5
|
+
|
6
|
+
def user_transactions(currency_pair: nil, offset: 0, limit: 100, sort: "desc")
|
7
|
+
path = path_with_currency_pair("/v2/user_transactions", currency_pair)
|
8
|
+
response = post(path, data: {offset: offset, limit: limit, sort: sort})
|
9
|
+
Bitstamper::Models::UserTransaction.parse(response) if response
|
10
|
+
end
|
11
|
+
|
12
|
+
def find_user_transaction(transaction_id)
|
13
|
+
user_transactions.select { |transaction| transaction.id == transaction_id }&.first
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Bitstamper
|
2
|
+
module Rest
|
3
|
+
module Private
|
4
|
+
module Withdrawals
|
5
|
+
|
6
|
+
def withdraw(currency, address:, amount:, instant: nil)
|
7
|
+
check_credentials!
|
8
|
+
|
9
|
+
currency = currency.to_s.downcase
|
10
|
+
|
11
|
+
if !::Bitstamper::Constants::AVAILABLE_CRYPTOS.include?(currency)
|
12
|
+
raise ::Bitstamper::Errors::InvalidCurrencyError.new("#{currency} is not a tradeable crypto currency on Bitstamp.")
|
13
|
+
end
|
14
|
+
|
15
|
+
path = currency.eql?("btc") ? "/bitcoin_withdrawal" : "/v2/#{currency}_withdrawal"
|
16
|
+
|
17
|
+
data = {
|
18
|
+
address: address,
|
19
|
+
amount: amount,
|
20
|
+
}
|
21
|
+
|
22
|
+
data[:instant] = 1 if (currency.eql?("btc") && (instant.eql?(true) || instant.eql?(1)))
|
23
|
+
|
24
|
+
response = parse(post(path, data: data))
|
25
|
+
response = response.is_a?(String) ? {"id" => response} : response
|
26
|
+
|
27
|
+
return response
|
28
|
+
end
|
29
|
+
|
30
|
+
def withdrawal_requests(interval: ::Bitstamper::Constants::TIME_IN_SECONDS[:day])
|
31
|
+
check_credentials!
|
32
|
+
|
33
|
+
response = post("/v2/withdrawal-requests", data: {timedelta: interval})
|
34
|
+
|
35
|
+
Bitstamper::Models::Withdrawal.parse(response) if response
|
36
|
+
end
|
37
|
+
|
38
|
+
def bank_withdrawal_status(id)
|
39
|
+
check_credentials!
|
40
|
+
|
41
|
+
response = post("/v2/withdrawal/status", data: {id: id})
|
42
|
+
end
|
43
|
+
|
44
|
+
def cancel_bank_withdrawal(id)
|
45
|
+
check_credentials!
|
46
|
+
|
47
|
+
response = post("/v2/withdrawal/cancel", data: {id: id})
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|