bitex 0.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +63 -0
  3. data/.rubocop.yml +32 -0
  4. data/.ruby-version +1 -0
  5. data/bitex.gemspec +21 -18
  6. data/lib/bitex.rb +7 -1
  7. data/lib/bitex/api.rb +34 -41
  8. data/lib/bitex/ask.rb +74 -0
  9. data/lib/bitex/base_order.rb +106 -0
  10. data/lib/bitex/bid.rb +72 -0
  11. data/lib/bitex/buy.rb +8 -5
  12. data/lib/bitex/kyc_file.rb +31 -9
  13. data/lib/bitex/kyc_profile.rb +113 -38
  14. data/lib/bitex/{market.rb → market_data.rb} +3 -3
  15. data/lib/bitex/match.rb +30 -15
  16. data/lib/bitex/order.rb +6 -238
  17. data/lib/bitex/payment.rb +30 -18
  18. data/lib/bitex/rates.rb +6 -8
  19. data/lib/bitex/sell.rb +5 -5
  20. data/lib/bitex/specie_deposit.rb +9 -4
  21. data/lib/bitex/specie_withdrawal.rb +29 -28
  22. data/lib/bitex/trade.rb +4 -5
  23. data/lib/bitex/transaction.rb +7 -8
  24. data/lib/bitex/usd_deposit.rb +46 -47
  25. data/lib/bitex/usd_withdrawal.rb +33 -34
  26. data/lib/bitex/version.rb +1 -1
  27. data/spec/ask_spec.rb +17 -5
  28. data/spec/bid_spec.rb +17 -5
  29. data/spec/buy_spec.rb +14 -4
  30. data/spec/kyc_file_spec.rb +34 -18
  31. data/spec/kyc_profile_spec.rb +158 -122
  32. data/spec/order_spec.rb +1 -1
  33. data/spec/payment_spec.rb +51 -45
  34. data/spec/sell_spec.rb +14 -4
  35. data/spec/spec_helper.rb +7 -6
  36. data/spec/specie_deposit_spec.rb +10 -4
  37. data/spec/specie_withdrawal_spec.rb +26 -25
  38. data/spec/support/from_json_shared_examples.rb +20 -22
  39. data/spec/support/order_shared_examples.rb +14 -17
  40. data/spec/support/request_stubs.rb +18 -12
  41. data/spec/trade_spec.rb +5 -5
  42. data/spec/transaction_spec.rb +12 -13
  43. data/spec/usd_deposit_spec.rb +120 -105
  44. data/spec/usd_withdrawal_spec.rb +89 -79
  45. metadata +57 -10
@@ -1,49 +1,61 @@
1
1
  module Bitex
2
+ ##
3
+ # Documentation here!
4
+ #
2
5
  class Payment
3
- attr_accessor :id, :user_id, :amount, :currency_id, :expected_quantity,
4
- :previous_expected_quantity, :confirmed_quantity, :unconfirmed_quantity,
5
- :valid_until, :quote_valid_until, :last_quoted_on, :status, :address,
6
- :settlement_currency_id, :settlement_amount, :keep, :merchant_reference,
7
- :customer_reference
6
+ attr_accessor :id, :user_id, :amount, :currency_id, :expected_quantity, :previous_expected_quantity, :confirmed_quantity,
7
+ :unconfirmed_quantity, :valid_until, :quote_valid_until, :last_quoted_on, :status, :address,
8
+ :settlement_currency_id, :settlement_amount, :keep, :merchant_reference, :customer_reference
8
9
 
9
10
  # @visibility private
10
11
  def self.from_json(json)
11
12
  new.tap do |thing|
12
- json.each do |key,raw_value|
13
+ json.each do |key, raw_value|
13
14
  next if raw_value.nil?
14
15
 
15
- value = if [:valid_until, :quote_valid_until, :last_quoted_on].include?(key.to_sym)
16
- Time.at(raw_value)
17
- else
18
- raw_value
16
+ value =
17
+ if %i[valid_until quote_valid_until last_quoted_on].include?(key)
18
+ Time.at(raw_value)
19
+ else
20
+ raw_value
21
+ end
22
+
23
+ begin
24
+ thing.send("#{key}=", value)
25
+ rescue NoMethodError
26
+ nil
19
27
  end
20
- thing.send("#{key}=", value) rescue nil
21
28
  end
22
29
  end
23
30
  end
24
31
 
25
32
  def self.create!(params)
26
- from_json(Api.private(:post, "/private/payments", params))
33
+ from_json(Api.private(:post, base_uri, params))
27
34
  end
28
35
 
29
36
  def self.find(id)
30
- from_json(Api.private(:get, "/private/payments/#{id}"))
37
+ from_json(Api.private(:get, "#{base_uri}/#{id}"))
31
38
  end
32
39
 
33
40
  def self.all
34
- Api.private(:get, "/private/payments").collect{|x| from_json(x) }
41
+ Api.private(:get, base_uri).map { |payment| from_json(payment) }
35
42
  end
36
-
43
+
37
44
  # Validate a callback and parse the given payment from it.
38
45
  # Returns nil if the callback was invalid.
39
46
  def self.from_callback(callback_params)
40
- from_json(callback_params["payment"]) if callback_params["api_key"] == Bitex.api_key
47
+ from_json(callback_params['payment']) if callback_params['api_key'] == Bitex.api_key
41
48
  end
42
49
 
43
50
  # Sets up the web-pos
44
51
  def self.pos_setup!(params)
45
- Api.private(:post, "/private/payments/pos_setup", params)
52
+ Api.private(:post, "#{base_uri}/pos_setup", params)
53
+ end
54
+
55
+ private_class_method
56
+
57
+ def self.base_uri
58
+ '/private/payments'
46
59
  end
47
60
  end
48
61
  end
49
-
@@ -8,18 +8,17 @@ module Bitex
8
8
  # Bitex::Rates.calculate_back([:ars, :cash, :usd, :bitex, :more_mt], 200)
9
9
  # @see https://bitex.la/developers#rates
10
10
  class Rates
11
-
12
11
  # Full exchange rates tree, gets cached locally for 60 seconds.
13
12
  def self.tree
14
13
  if @tree.nil? || @last_tree_fetch.to_i < (Time.now.to_i - 60)
15
- @tree = Api.public("/rates/tree").deep_symbolize_keys
14
+ @tree = Api.public('/rates/tree').deep_symbolize_keys
16
15
  @last_tree_fetch = Time.now.to_i
17
16
  end
18
17
  @tree
19
18
  end
20
-
19
+
21
20
  def self.clear_tree_cache
22
- @tree = nil
21
+ @tree = nil
23
22
  @last_tree_fetch = nil
24
23
  end
25
24
 
@@ -40,7 +39,7 @@ module Bitex
40
39
  end
41
40
  value
42
41
  end
43
-
42
+
44
43
  def self.calculate_path_backwards(path, value)
45
44
  value = value.to_d
46
45
  path_to_calculator(path).each do |step|
@@ -53,13 +52,12 @@ module Bitex
53
52
  when :fixed_fee
54
53
  value += step[:amount].to_d
55
54
  when :minimum_fee
56
- value = [value + step[:minimum].to_d,
57
- value / (1 - (step[:percentage].to_d / 100.to_d))].max
55
+ value = [value + step[:minimum].to_d, value / (1 - (step[:percentage].to_d / 100.to_d))].max
58
56
  end
59
57
  end
60
58
  value
61
59
  end
62
-
60
+
63
61
  def self.path_to_calculator(path)
64
62
  steps = tree
65
63
  begin
@@ -7,18 +7,18 @@ module Bitex
7
7
  # @!attribute created_at
8
8
  # @return [Time] Time when this Sell happened.
9
9
 
10
- # @!attribute specie
11
- # @return [Symbol] :btc or :ltc
12
-
10
+ # @!attribute orderbook
11
+ # @return [Symbol] :btc_usd or :btc_ars
12
+
13
13
  # @!attribute quantity
14
14
  # @return [BigDecimal] Quantity of specie sold
15
-
15
+
16
16
  # @!attribute amount
17
17
  # @return [BigDecimal] Amount of USD earned
18
18
 
19
19
  # @!attribute fee
20
20
  # @return [BigDecimal] USD amount paid as transaction fee.
21
-
21
+
22
22
  # @!attribute price
23
23
  # @return [BigDecimal] Price charged per unit
24
24
 
@@ -10,7 +10,7 @@ module Bitex
10
10
  attr_accessor :created_at
11
11
 
12
12
  # @!attribute specie
13
- # @return [Symbol] :btc or :ltc
13
+ # @return [Symbol] :btc
14
14
  attr_accessor :specie
15
15
 
16
16
  # @!attribute quantity
@@ -19,8 +19,9 @@ module Bitex
19
19
 
20
20
  # @visibility private
21
21
  def self.from_json(json)
22
- Api.from_json(new, json, true) do |thing|
23
- thing.quantity = BigDecimal.new(json[4].to_s)
22
+ Api.from_json(new, json) do |thing|
23
+ thing.specie = { 1 => :btc }[json[3]]
24
+ thing.quantity = (json[4] || 0).to_d
24
25
  end
25
26
  end
26
27
 
@@ -29,7 +30,11 @@ module Bitex
29
30
  end
30
31
 
31
32
  def self.all(specie)
32
- Api.private(:get, "/private/#{specie}/deposits").collect{|x| from_json(x) }
33
+ Api.private(:get, "/private/#{specie}/deposits").map { |sd| from_json(sd) }
34
+ end
35
+
36
+ def self.species
37
+ { 0 => :btc }
33
38
  end
34
39
  end
35
40
  end
@@ -10,13 +10,13 @@ module Bitex
10
10
  attr_accessor :created_at
11
11
 
12
12
  # @!attribute specie
13
- # @return [Symbol] :btc or :ltc
13
+ # @return [Symbol] :btc
14
14
  attr_accessor :specie
15
15
 
16
16
  # @!attribute quantity
17
17
  # @return [BigDecimal] Quantity deposited
18
18
  attr_accessor :quantity
19
-
19
+
20
20
  # @!attribute status
21
21
  # Returns the status of this withdrawal.
22
22
  # * :received Our engine is checking if you have enough funds.
@@ -40,32 +40,22 @@ module Bitex
40
40
  # @!attribute label
41
41
  # @return [String] A custom label you gave to this address.
42
42
  attr_accessor :label
43
-
43
+
44
44
  # @!attribute kyc_profile_id
45
45
  # @return [Integer] Kyc profile id for which this request was made.
46
46
  attr_accessor :kyc_profile_id
47
47
 
48
48
  # @!attribute transaction_id
49
- # @return [String] Network transaction id, if available.
49
+ # @return [String] Network transaction id, if available.
50
50
  attr_accessor :transaction_id
51
51
 
52
52
  # @visibility private
53
53
  def self.from_json(json)
54
- status_lookup = {
55
- 1 => :received,
56
- 2 => :pending,
57
- 3 => :done,
58
- 4 => :cancelled,
59
- }
60
- reason_lookup = {
61
- 0 => :not_cancelled,
62
- 1 => :insufficient_funds,
63
- 2 => :destination_invalid,
64
- }
65
- Api.from_json(new, json, true) do |thing|
66
- thing.quantity = BigDecimal.new(json[4].to_s)
67
- thing.status = status_lookup[json[5]]
68
- thing.reason = reason_lookup[json[6]]
54
+ Api.from_json(new, json) do |thing|
55
+ thing.specie = { 1 => :btc }[json[3]]
56
+ thing.quantity = (json[4].presence || 0).to_d
57
+ thing.status = statuses[json[5]]
58
+ thing.reason = reasons[json[6]]
69
59
  thing.to_address = json[7]
70
60
  thing.label = json[8]
71
61
  thing.kyc_profile_id = json[9]
@@ -73,13 +63,17 @@ module Bitex
73
63
  end
74
64
  end
75
65
 
76
- def self.create!(specie, address, amount, label, kyc_profile_id=nil)
77
- from_json(Api.private(:post, "/private/#{specie}/withdrawals", {
78
- address: address,
79
- amount: amount,
80
- label: label,
81
- kyc_profile_id: kyc_profile_id
82
- }))
66
+ def self.create!(specie, address, amount, label, kyc_profile_id = nil)
67
+ from_json(
68
+ Api.private(
69
+ :post,
70
+ "/private/#{specie}/withdrawals",
71
+ address: address,
72
+ amount: amount,
73
+ label: label,
74
+ kyc_profile_id: kyc_profile_id
75
+ )
76
+ )
83
77
  end
84
78
 
85
79
  def self.find(specie, id)
@@ -87,8 +81,15 @@ module Bitex
87
81
  end
88
82
 
89
83
  def self.all(specie)
90
- Api.private(:get, "/private/#{specie}/withdrawals")
91
- .collect{|x| from_json(x) }
84
+ Api.private(:get, "/private/#{specie}/withdrawals").map { |sw| from_json(sw) }
85
+ end
86
+
87
+ def self.statuses
88
+ { 1 => :received, 2 => :pending, 3 => :done, 4 => :cancelled }
89
+ end
90
+
91
+ def self.reasons
92
+ { 0 => :not_cancelled, 1 => :insufficient_funds, 2 => :destination_invalid }
92
93
  end
93
94
  end
94
95
  end
@@ -1,13 +1,12 @@
1
1
  module Bitex
2
- # Utility class for fetching an heterogeneous list of objects that
3
- # compose your transaction history.
2
+ # Utility class for fetching an heterogeneous list of objects that compose your transaction history.
3
+ #
4
4
  class Trade
5
5
  # @return [Array<Bitex::Buy, Bitex::Sell]
6
- # Returns an heterogeneous array with all your transactions for the past
7
- # 30 days sorted by descending date.
6
+ # Returns an heterogeneous array with all your transactions for the past 30 days sorted by descending date.
8
7
  # @see https://bitex.la/developers#user-trades
9
8
  def self.all
10
- Api.private(:GET, '/private/trades').collect{|o| Api.deserialize(o) }
9
+ Api.private(:GET, '/private/trades').map { |t| Api.deserialize(t) }
11
10
  end
12
11
  end
13
12
  end
@@ -1,14 +1,13 @@
1
1
  module Bitex
2
- # Utility class for fetching an heterogeneous list of objects that
3
- # compose your transaction history.
4
- class Transaction
5
- # @return [Array<Bitex::Bid, Bitex::Ask, Bitex::SpecieDeposit,
6
- # Bitex::SpecieWithdrawal, Bitex::UsdDeposit, Bitex::UsdWithdrawal>]
7
- # Returns an heterogeneous array with all your transactions for the past
8
- # 15 days sorted by descending date.
2
+ # Utility class for fetching an heterogeneous list of objects that compose your transaction history.
3
+ #
4
+ class Transaction
5
+ # @return
6
+ # [Array<Bitex::Bid, Bitex::Ask, Bitex::SpecieDeposit, Bitex::SpecieWithdrawal, Bitex::UsdDeposit, Bitex::UsdWithdrawal>]
7
+ # Returns an heterogeneous array with all your transactions for the past 15 days sorted by descending date.
9
8
  # @see https://bitex.la/developers#user-account-summary
10
9
  def self.all
11
- Api.private(:GET, '/private/account_summary').collect{|o| Api.deserialize(o) }
10
+ Api.private(:GET, '/private/account_summary').map { |t| Api.deserialize(t) }
12
11
  end
13
12
  end
14
13
  end
@@ -1,5 +1,6 @@
1
1
  module Bitex
2
2
  # A deposit of USD to your bitex.la balance.
3
+ #
3
4
  class UsdDeposit
4
5
  # @!attribute id
5
6
  # @return [Integer] This UsdDeposit's unique ID.
@@ -10,14 +11,13 @@ module Bitex
10
11
  attr_accessor :created_at
11
12
 
12
13
  # @!attribute requested_amount
13
- # @return [BigDecimal] For pre-announced deposits, this is the amount you
14
- # requested to deposit.
14
+ # @return [BigDecimal] For pre-announced deposits, this is the amount you requested to deposit.
15
15
  attr_accessor :requested_amount
16
16
 
17
17
  # @!attribute amount
18
18
  # @return [BigDecimal] Final amount credited to your bitex USD balance.
19
19
  attr_accessor :amount
20
-
20
+
21
21
  # @!attribute deposit_method
22
22
  # The method used for this deposit
23
23
  # * :astropay
@@ -26,10 +26,8 @@ module Bitex
26
26
 
27
27
  # @!attribute status
28
28
  # The status of this deposit.
29
- # * :pending your deposit notice was received, we're waiting for the funds
30
- # to credit.
31
- # * :done your deposit credited correctly, the funds are available in your
32
- # balance.
29
+ # * :pending your deposit notice was received, we're waiting for the funds to credit.
30
+ # * :done your deposit credited correctly, the funds are available in your balance.
33
31
  # * :cancelled your deposit did not credit, check the 'reason' field.
34
32
  attr_accessor :status
35
33
 
@@ -37,28 +35,27 @@ module Bitex
37
35
  # The reason for cancellation of this deposit, if any.
38
36
  # * :not_cancelled.
39
37
  # * :did_not_credit funds never arrived to our end.
40
- # * :sender_unknown we could not accept these funds because you're not the
41
- # sender.
38
+ # * :sender_unknown we could not accept these funds because you're not the sender.
42
39
  # * :other we'll contact you regarding this deposit.
43
40
  # * :user_cancelled We cancelled this deposit per your request.
44
41
  attr_accessor :reason
45
-
42
+
46
43
  # @!attribute country
47
44
  # Country of origin for this deposit.
48
45
  attr_accessor :country
49
-
46
+
50
47
  # @!attribute currency
51
48
  # Local currency for the country.
52
49
  attr_accessor :currency
53
-
50
+
54
51
  # @!attribute kyc_profile_id
55
52
  # KYC profile on whose behalf this deposit is being created.
56
53
  attr_accessor :kyc_profile_id
57
-
54
+
58
55
  # @!attribute request_details
59
56
  # Details for our account officers about this deposit.
60
57
  attr_accessor :request_details
61
-
58
+
62
59
  # @!attribute astropay_response_body
63
60
  # Response from astropay if selected as the deposit method.
64
61
  # The 'url' field should be the astropay payment url for this deposit.
@@ -69,29 +66,14 @@ module Bitex
69
66
  attr_accessor :third_party_reference
70
67
 
71
68
  # @visibility private
69
+ # rubocop:disable Metrics/AbcSize
72
70
  def self.from_json(json, deposit = nil)
73
- deposit_method_lookup = {
74
- 1 => :astropay,
75
- 2 => :other,
76
- }
77
- status_lookup = {
78
- 1 => :pending,
79
- 2 => :done,
80
- 3 => :cancelled,
81
- }
82
- reason_lookup = {
83
- 0 => :not_cancelled,
84
- 1 => :did_not_credit,
85
- 2 => :sender_unknown,
86
- 3 => :other,
87
- 4 => :user_cancelled,
88
- }
89
71
  Api.from_json(deposit || new, json) do |thing|
90
- thing.requested_amount = BigDecimal.new(json[3].to_s)
91
- thing.amount = BigDecimal.new(json[4].to_s)
92
- thing.deposit_method = deposit_method_lookup[json[5]]
93
- thing.status = status_lookup[json[6]]
94
- thing.reason = reason_lookup[json[7]]
72
+ thing.requested_amount = (json[3].presence || 0).to_d
73
+ thing.amount = (json[4].presence || 0).to_d
74
+ thing.deposit_method = deposit_methods[json[5]]
75
+ thing.status = statuses[json[6]]
76
+ thing.reason = reasons[json[7]]
95
77
  thing.country = json[8]
96
78
  thing.currency = json[9]
97
79
  thing.kyc_profile_id = json[10]
@@ -100,29 +82,46 @@ module Bitex
100
82
  thing.third_party_reference = json[13]
101
83
  end
102
84
  end
85
+ # rubocop:enable Metrics/AbcSize
103
86
 
104
- def self.create!(country, amount, currency, method, details, profile=nil)
105
- from_json(Api.private(:post, "/private/usd/deposits", {
106
- country: country,
107
- amount: amount,
108
- currency: currency,
109
- deposit_method: method,
110
- request_details: details,
111
- kyc_profile_id: profile,
112
- }))
87
+ def self.create!(country, amount, currency, method, details, profile = nil)
88
+ from_json(
89
+ Api.private(
90
+ :post,
91
+ '/private/usd/deposits',
92
+ country: country,
93
+ amount: amount,
94
+ currency: currency,
95
+ deposit_method: method,
96
+ request_details: details,
97
+ kyc_profile_id: profile
98
+ )
99
+ )
113
100
  end
114
-
101
+
115
102
  def self.find(id)
116
103
  from_json(Api.private(:get, "/private/usd/deposits/#{id}"))
117
104
  end
118
105
 
119
106
  def cancel!
120
- path = "/private/usd/deposits/#{self.id}/cancel"
107
+ path = "/private/usd/deposits/#{id}/cancel"
121
108
  self.class.from_json(Api.private(:post, path), self)
122
109
  end
123
110
 
124
111
  def self.all
125
- Api.private(:get, "/private/usd/deposits").collect{|x| from_json(x) }
112
+ Api.private(:get, '/private/usd/deposits').map { |d| from_json(d) }
113
+ end
114
+
115
+ def self.deposit_methods
116
+ { 1 => :astropay, 2 => :other }
117
+ end
118
+
119
+ def self.statuses
120
+ { 1 => :pending, 2 => :done, 3 => :cancelled }
121
+ end
122
+
123
+ def self.reasons
124
+ { 0 => :not_cancelled, 1 => :did_not_credit, 2 => :sender_unknown, 3 => :other, 4 => :user_cancelled }
126
125
  end
127
126
  end
128
127
  end