excoin 0.0.1

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.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +32 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE.txt +674 -0
  5. data/README.md +278 -0
  6. data/Rakefile +9 -0
  7. data/config/config.example.yml +16 -0
  8. data/excoin.gemspec +26 -0
  9. data/lib/account/account.rb +116 -0
  10. data/lib/account/deposit.rb +20 -0
  11. data/lib/account/order.rb +43 -0
  12. data/lib/account/orders.rb +138 -0
  13. data/lib/account/trade.rb +26 -0
  14. data/lib/account/trades.rb +59 -0
  15. data/lib/account/wallet.rb +72 -0
  16. data/lib/account/withdrawal.rb +27 -0
  17. data/lib/exchange/candlestick_chart.rb +33 -0
  18. data/lib/exchange/candlestick_data.rb +20 -0
  19. data/lib/exchange/exchange.rb +75 -0
  20. data/lib/exchange/market.rb +50 -0
  21. data/lib/exchange/order.rb +23 -0
  22. data/lib/exchange/order_depth_chart.rb +41 -0
  23. data/lib/exchange/order_depth_data.rb +23 -0
  24. data/lib/exchange/orders.rb +119 -0
  25. data/lib/exchange/trade.rb +26 -0
  26. data/lib/exchange/trades.rb +68 -0
  27. data/lib/excoin.rb +45 -0
  28. data/lib/excoin/api.rb +212 -0
  29. data/lib/excoin/version.rb +10 -0
  30. data/spec/fixtures/cassette_library/account_cancel_order_erb.yml +59 -0
  31. data/spec/fixtures/cassette_library/account_issue_order_erb.yml +59 -0
  32. data/spec/fixtures/cassette_library/account_view_order_erb.yml +59 -0
  33. data/spec/fixtures/cassette_library/exc_recent_trades.yml +157 -0
  34. data/spec/fixtures/cassette_library/exc_recent_trades_count.yml +62 -0
  35. data/spec/fixtures/cassette_library/exc_recent_trades_timestamp.yml +142 -0
  36. data/spec/fixtures/cassette_library/exchange_candlestick_chart_data.yml +58 -0
  37. data/spec/fixtures/cassette_library/exchange_candlestick_chart_data_duration.yml +58 -0
  38. data/spec/fixtures/cassette_library/exchange_open_orders.yml +58 -0
  39. data/spec/fixtures/cassette_library/exchange_open_orders_type.yml +58 -0
  40. data/spec/fixtures/cassette_library/exchange_order_depth_chart_data.yml +58 -0
  41. data/spec/fixtures/cassette_library/excoin_wallet_reserves.yml +59 -0
  42. data/spec/fixtures/cassette_library/excoin_wallets_summary.yml +65 -0
  43. data/spec/fixtures/cassette_library/excoin_wallets_summary_coin.yml +59 -0
  44. data/spec/fixtures/cassette_library/multi_exchange_summ.yml +58 -0
  45. data/spec/fixtures/cassette_library/multi_exchange_summ_currency.yml +58 -0
  46. data/spec/fixtures/cassette_library/single_exchange_summ.yml +58 -0
  47. data/spec/fixtures/cassette_library/single_exchange_summary.yml +58 -0
  48. data/spec/lib/account/account_spec.rb +136 -0
  49. data/spec/lib/account/orders_spec.rb +51 -0
  50. data/spec/lib/account/trades_spec.rb +52 -0
  51. data/spec/lib/account/wallet_spec.rb +67 -0
  52. data/spec/lib/exchange/candlestick_chart_spec.rb +23 -0
  53. data/spec/lib/exchange/exchange_spec.rb +38 -0
  54. data/spec/lib/exchange/market_spec.rb +23 -0
  55. data/spec/lib/exchange/order_depth_chart_spec.rb +20 -0
  56. data/spec/lib/exchange/orders_spec.rb +47 -0
  57. data/spec/lib/exchange/trades_spec.rb +50 -0
  58. data/spec/lib/excoin/api_spec.rb +228 -0
  59. data/spec/lib/excoin_spec.rb +28 -0
  60. data/spec/spec_helper.rb +46 -0
  61. data/spec/support/vcr.rb +21 -0
  62. metadata +209 -0
@@ -0,0 +1,20 @@
1
+ class Excoin::Account::Wallet::Deposit
2
+ attr_reader :timestamp, :currency, :id, :address,
3
+ :amount, :confirmations, :confirmed
4
+
5
+ def initialize(deposit_data)
6
+ begin
7
+ @timestamp = Time.parse(deposit_data['timestamp'])
8
+ @currency = deposit_data['currency']
9
+ @id = deposit_data['txid']
10
+ @address = deposit_data['address']
11
+ @amount = BigDecimal.new(deposit_data['amount'])
12
+ @confirmations = deposit_data['confirmations']
13
+ @confirmed = deposit_data['confirmed']
14
+ rescue
15
+ puts "Error in Excoin::Account::Deposit.initialize"
16
+ puts deposit_data
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,43 @@
1
+ class Excoin::Account::Order
2
+ attr_reader :currency, :commodity, :type, :id, :timestamp, :price,
3
+ :commodity_amount, :currency_amount, :status
4
+
5
+ def initialize(order_data)
6
+ self.update(order_data)
7
+ end
8
+
9
+ def update(order_data)
10
+ begin
11
+ unless order_data['currency'] and order_data['commodity']
12
+ order_data.merge!({"currency" => order_data['id'].split("-").first, "commodity" => order_data['id'].split("-")[1]})
13
+ end
14
+ @currency ||= order_data['currency']
15
+ @commodity ||= order_data['commodity']
16
+ @type ||= order_data['type']
17
+ @id ||= order_data['id']
18
+ @timestamp ||= Time.parse(order_data['timestamp'])
19
+ @price = BigDecimal.new(order_data['price'])
20
+ @currency_amount = BigDecimal.new(order_data['currency_amount'])
21
+ @commodity_amount = BigDecimal.new(order_data['commodity_amount'])
22
+ @status = order_data['status']
23
+ rescue
24
+ puts "Error in Excoin::Account::Order.update"
25
+ puts order_data
26
+ end
27
+ end
28
+
29
+ def exchange
30
+ Excoin.market.exchange(@currency + @commodity)
31
+ end
32
+
33
+ def refresh
34
+ order_data = Excoin.api.account_view_order(self.id)
35
+ self.update(order_data)
36
+ end
37
+
38
+ def cancel
39
+ order_data = Excoin.api.account_cancel_order(self.id)
40
+ self.update(order_data)
41
+ end
42
+
43
+ end
@@ -0,0 +1,138 @@
1
+ class Excoin::Account::Orders < Array
2
+
3
+ def initialize
4
+ self.refresh
5
+ end
6
+
7
+ def update(exchange_name = nil)
8
+ begin
9
+ unless exchange_name
10
+ all_orders = populate_all_orders
11
+ all_orders.each do |exchange_order_set|
12
+ self.select{|h| h['exchange_name'] == exchange_order_set['exchange_name']}.first.merge!(exchange_order_set)
13
+ end
14
+ else
15
+ exchange = Excoin.market.exchange(exchange_name)
16
+ exchange_order_data = self.get(exchange.currency, exchange.commodity)
17
+ exchange_orders = self.process_orders_by_exchange(exchange_order_data)
18
+ self.select{|h| h['currency'] == currency and h['commodity'] == commodity}.first.merge!(exchange_orders)
19
+ end
20
+ rescue
21
+ puts "Error in Excoin::Account::Orders.update"
22
+ puts exchange_order_data
23
+ end
24
+ end
25
+
26
+ def refresh
27
+ self.clear
28
+ all_orders = self.populate_all_orders
29
+ all_orders.each do |exchange_order_set|
30
+ self.push(exchange_order_set)
31
+ end
32
+ end
33
+
34
+ def all
35
+ self.collect{|order_set| order_set.select{|k,v| k =~ Regexp.new("_orders")}.values}.collect{|orders| orders}.flatten
36
+ end
37
+
38
+ def add(order)
39
+ begin
40
+ self.select{|exchange_order_set| exchange_order_set.has_value?(order.currency + order.commodity)}[0].select{|k,v| k =~ Regexp.new(order.type.downcase)}[order.type.downcase + "_orders"] << order
41
+ rescue
42
+ puts "Error in Excoin::Account::Orders.add"
43
+ puts order
44
+ end
45
+ end
46
+
47
+ def delete(order_data)
48
+ begin
49
+ self.select{|exchange_order_set| exchange_order_set.has_value?(order_data['currency'] + order_data['commodity'])}[0].select{|k,v| k =~ Regexp.new(order_data['type'].downcase)}[order_data['type'].downcase + "_orders"].delete_at(self.select{|exchange_order_set| exchange_order_set.has_value?(order_data['currency'] + order_data['commodity'])}[0].select{|k,v| k =~ Regexp.new(order_data['type'].downcase)}[order_data['type'].downcase + "_orders"].find_index{|order| order.id == order_data['id']})
50
+ rescue
51
+ puts "Error in Excoin::Account::Orders.delete"
52
+ puts order_data
53
+ end
54
+ end
55
+
56
+ def filter(attr, value, operator = :==)
57
+ orders_by_attr = Array.new
58
+ if attr == "currency" or attr == "commodity" or attr == "exchange_name"
59
+ self.select{|h| h[attr] == value}.each do |h|
60
+ h.select{|k,v| k =~ Regexp.new("_orders")}.each_value do |orders|
61
+ orders.each do |order|
62
+ orders_by_attr << order
63
+ end
64
+ end
65
+ end
66
+ else
67
+ self.each do |h|
68
+ if attr == "type"
69
+ h.select{|k,v| k =~ Regexp.new(value.upcase)}.each_value do |orders|
70
+ orders.each do |order|
71
+ orders_by_attr << order
72
+ end
73
+ end
74
+ else
75
+ h.select{|k,v| k =~ Regexp.new("_orders")}.each_value do |orders|
76
+ orders.each do |order|
77
+ value = BigDecimal.new(value)
78
+ if order.send(attr).send(operator, value)
79
+ orders_by_attr << order
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ return orders_by_attr
87
+ end
88
+
89
+ def count(attr = nil, value = nil, operator = :==)
90
+ if attr
91
+ return self.filter(attr, value, operator).size
92
+ else
93
+ count = 0
94
+ self.each do |h|
95
+ # maybe this can be redone with inject
96
+ h.select{|k,v| k =~ /_orders/}.each_pair do |k,v|
97
+ count += v.size
98
+ end
99
+ end
100
+ return count
101
+ end
102
+ end
103
+
104
+ protected
105
+
106
+ def get(currency = nil, commodity = nil, type = nil)
107
+ Excoin.api.account_open_orders(currency, commodity, type)
108
+ end
109
+
110
+ def process_orders_by_exchange(exchange_order_data)
111
+ begin
112
+ currency = exchange_order_data.select{|k,v| k == 'currency'}
113
+ commodity = exchange_order_data.select{|k,v| k == 'commodity'}
114
+ exchange_orders = {"exchange_name" => currency['currency'] + commodity['commodity']}.merge(currency).merge(commodity)
115
+ exchange_order_data['orders'].each do |hash_by_type|
116
+ orders_by_type = Array.new
117
+ type = hash_by_type.select{|k,v| k == 'type'}
118
+ hash_by_type['orders'].each do |o|
119
+ o.merge!(type).merge!(currency).merge!(commodity)
120
+ order = Excoin::Account::Order.new(o)
121
+ orders_by_type << order
122
+ end
123
+ exchange_orders.merge!({ "#{type['type'].downcase}_orders" => orders_by_type})
124
+ end
125
+ return exchange_orders
126
+ rescue
127
+ puts "Error in Excoin::Account::Orders.process_orders_by_exchange"
128
+ puts exchange_order_data
129
+ end
130
+ end
131
+
132
+ def populate_all_orders
133
+ order_data = self.get
134
+ orders = order_data.collect{|exchange_order_data| self.process_orders_by_exchange(exchange_order_data)}
135
+ return orders
136
+ end
137
+
138
+ end
@@ -0,0 +1,26 @@
1
+ class Excoin::Account::Trade
2
+ attr_reader :timestamp, :currency, :commodity, :type, :price, :sent,
3
+ :received, :fee, :net_received
4
+
5
+ def initialize(trade_data)
6
+ begin
7
+ @timestamp = Time.parse(trade_data['timestamp'])
8
+ @currency = trade_data['currency']
9
+ @commodity = trade_data['commodity']
10
+ @type = trade_data['type']
11
+ @price = BigDecimal.new(trade_data['price'])
12
+ @sent = BigDecimal.new(trade_data['sent'])
13
+ @received = BigDecimal.new(trade_data['received'])
14
+ @fee = BigDecimal.new(trade_data['fee'])
15
+ @net_received = BigDecimal.new(trade_data['net_received'])
16
+ rescue
17
+ puts "Error in Excoin::Account::Trade.initialize"
18
+ puts trade_data
19
+ end
20
+ end
21
+
22
+ def exchange
23
+ Excoin.market.exchange(@currency + @commodity)
24
+ end
25
+
26
+ end
@@ -0,0 +1,59 @@
1
+ class Excoin::Account::Trades < Array
2
+
3
+ def initialize
4
+ self.update
5
+ end
6
+
7
+ def update(count = 100)
8
+ self.clear
9
+ recent_trade_data = self.get(count)
10
+ begin
11
+ recent_trade_data['trades'].each do |trade_data|
12
+ trade = Excoin::Account::Trade.new(trade_data)
13
+ self.push(trade)
14
+ end
15
+ rescue
16
+ puts "Error in Excoin::Account::Trades.update"
17
+ puts recent_trade_data
18
+ end
19
+ end
20
+
21
+ def buys
22
+ self.select{|trade| trade.type == "BUY"}
23
+ end
24
+
25
+ def sells
26
+ self.select{|trade| trade.type == "SELL"}
27
+ end
28
+
29
+ def highest(type = nil)
30
+ unless type
31
+ self.max_by{|trade| trade.price}
32
+ else
33
+ self.select{|trade| trade.type == type.upcase}.max_by{|trade| trade.price}
34
+ end
35
+ end
36
+
37
+ def lowest(type = nil)
38
+ unless type
39
+ self.min_by{|trade| trade.price}
40
+ else
41
+ self.select{|trade| trade.type == type.upcase}.min_by{|trade| trade.price}
42
+ end
43
+ end
44
+
45
+ def add(trade_data)
46
+ self.insert(0, Excoin::Account::Trade.new(trade_data))
47
+ end
48
+
49
+ def trim(number)
50
+ self.pop(number)
51
+ end
52
+
53
+ protected
54
+
55
+ def get(count = 100)
56
+ Excoin.api.account_trades(count)
57
+ end
58
+
59
+ end
@@ -0,0 +1,72 @@
1
+ class Excoin::Account::Wallet
2
+ attr_reader :status, :currency, :deposit_address, :confirmed_balance,
3
+ :available_balance, :order_balance,
4
+ :pending_deposit_balance, :pending_withdrawal_balance,
5
+ :deposits, :withdrawals
6
+
7
+ def initialize(active, wallet_data)
8
+ begin
9
+ if active
10
+ @status = "active"
11
+ @currency = wallet_data['currency']
12
+ @deposits = Hash.new
13
+ @withdrawals = Hash.new
14
+ @deposit_address = wallet_data['address']
15
+ @confirmed_balance = BigDecimal.new(wallet_data['confirmed_balance'])
16
+ @available_balance = BigDecimal.new(wallet_data['available_balance'])
17
+ @order_balance = BigDecimal.new(wallet_data['order_balance'])
18
+ @pending_deposit_balance = BigDecimal.new(wallet_data['pending_deposit_balance'])
19
+ @pending_withdrawal_balance = BigDecimal.new(wallet_data['pending_withdrawal_balance'])
20
+ else
21
+ @status = "inactive"
22
+ @currency = wallet_data['currency']
23
+ @deposit_address = wallet_data['address']
24
+ end
25
+ rescue
26
+ puts "Error in Excoin::Account::Wallet.initialize"
27
+ puts wallet_data
28
+ end
29
+ end
30
+
31
+ def update(wallet_data)
32
+ begin
33
+ if wallet_data['address']
34
+ @deposit_address = wallet_data['address']
35
+ end
36
+ @confirmed_balance = BigDecimal.new(wallet_data['confirmed_balance'])
37
+ @available_balance = BigDecimal.new(wallet_data['available_balance'])
38
+ @order_balance = BigDecimal.new(wallet_data['order_balance'])
39
+ @pending_deposit_balance = BigDecimal.new(wallet_data['pending_deposit_balance'])
40
+ @pending_withdrawal_balance = BigDecimal.new(wallet_data['pending_withdrawal_balance'])
41
+ rescue
42
+ puts "Error in Excoin::Account::Wallet.update"
43
+ puts wallet_data
44
+ end
45
+ end
46
+
47
+ def unconfirmed_deposits
48
+ return @deposits.select{|id, deposit_object| deposit_object.confirmed == false}
49
+ end
50
+
51
+ def unconfirmed_withdrawals
52
+ return @withdrawals.select{|id, withdrawal_object| withdrawal_object.confirmed == false}
53
+ end
54
+
55
+ def add_deposit(deposit_data)
56
+ @deposits.merge!({deposit_data['txid'] => Deposit.new(deposit_data)})
57
+ end
58
+
59
+ def add_withdrawal(withdrawal_data)
60
+ @withdrawals.merge!({withdrawal_data['id'] => Withdrawal.new(withdrawal_data)})
61
+ end
62
+
63
+ def withdraw(address, amount)
64
+ if BigDecimal.new(amount) <= self.available_balance
65
+ withdrawal_data = Excoin.api.account_withdraw(self.currency, address, amount)
66
+ Excoin.account.add_withdrawal(withdrawal_data)
67
+ else
68
+ puts "Insufficient funds for withdrawal"
69
+ end
70
+ end
71
+
72
+ end
@@ -0,0 +1,27 @@
1
+ class Excoin::Account::Wallet::Withdrawal
2
+ attr_reader :id, :timestamp, :currency, :address,
3
+ :amount, :confirmed
4
+
5
+ def initialize(withdrawal_data)
6
+ begin
7
+ @id = withdrawal_data['id']
8
+ @timestamp = Time.parse(withdrawal_data['timestamp'])
9
+ @currency = withdrawal_data['currency']
10
+ @address = withdrawal_data['address']
11
+ @amount = BigDecimal.new(withdrawal_data['amount'])
12
+ @confirmed = withdrawal_data['confirmed']
13
+ rescue
14
+ puts "Error in Excoin::Account::Withdrawal.initialize"
15
+ puts withdrawal_data
16
+ end
17
+ end
18
+
19
+ ## to be implemented in API in the future
20
+ #
21
+ # def cancel_withdrawal(withdrawal_id)
22
+ # end
23
+ #
24
+ # def initiate_withdrawal
25
+ # end
26
+
27
+ end
@@ -0,0 +1,33 @@
1
+ class Excoin::Market::Exchange::CandlestickChart
2
+ attr_reader :currency, :commodity, :datapoints
3
+
4
+ def initialize(exchange_name)
5
+ @exchange_name = exchange_name
6
+ exchange = self.exchange
7
+
8
+ @currency = exchange.currency
9
+ @commodity = exchange.commodity
10
+
11
+ @datapoints = Array.new
12
+ self.update
13
+ end
14
+
15
+ def update
16
+ @datapoints.clear
17
+ chart_data = self.get
18
+ chart_data.each do |point|
19
+ datapoint = DataPoint.new(point)
20
+ @datapoints << datapoint
21
+ end
22
+ end
23
+
24
+ def exchange
25
+ return Excoin.market.exchange(@exchange_name)
26
+ end
27
+
28
+ protected
29
+ def get
30
+ Excoin.api.exchange_candlestick_chart_data(@currency, @commodity)
31
+ end
32
+
33
+ end
@@ -0,0 +1,20 @@
1
+ class Excoin::Market::Exchange::CandlestickChart::DataPoint
2
+ attr_reader :timestamp, :open, :close, :high, :low, :commodity_volume,
3
+ :currency_volume
4
+
5
+ def initialize(exchange_data)
6
+ begin
7
+ @timestamp = Time.parse(exchange_data['timestamp'])
8
+ @open = BigDecimal.new(exchange_data['open'])
9
+ @close = BigDecimal.new(exchange_data['close'])
10
+ @high = BigDecimal.new(exchange_data['high'])
11
+ @low = BigDecimal.new(exchange_data['low'])
12
+ @commodity_volume = BigDecimal.new(exchange_data['commodity_volume'])
13
+ @currency_volume = BigDecimal.new(exchange_data['currency_volume'])
14
+ rescue
15
+ puts "Error in Excoin::Market::Exchange::CandlestickChart::Datapoint"
16
+ puts exchange_data
17
+ end
18
+ end
19
+
20
+ end