coinfresh 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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/coinfresh.gemspec +27 -0
  8. data/lib/coinfresh.rb +59 -0
  9. data/lib/coinfresh/api/base.rb +18 -0
  10. data/lib/coinfresh/api/cash_flow.rb +20 -0
  11. data/lib/coinfresh/api/currency.rb +19 -0
  12. data/lib/coinfresh/api/market.rb +25 -0
  13. data/lib/coinfresh/api/order.rb +43 -0
  14. data/lib/coinfresh/api/wallet.rb +21 -0
  15. data/lib/coinfresh/api/withdraw.rb +21 -0
  16. data/lib/coinfresh/api_operation/create.rb +12 -0
  17. data/lib/coinfresh/api_operation/destroy.rb +11 -0
  18. data/lib/coinfresh/api_operation/find.rb +16 -0
  19. data/lib/coinfresh/api_operation/list.rb +13 -0
  20. data/lib/coinfresh/api_operation/new.rb +11 -0
  21. data/lib/coinfresh/api_operation/update.rb +12 -0
  22. data/lib/coinfresh/client.rb +39 -0
  23. data/lib/coinfresh/http.rb +106 -0
  24. data/lib/coinfresh/model/base.rb +175 -0
  25. data/lib/coinfresh/model/cash_flow.rb +17 -0
  26. data/lib/coinfresh/model/currency.rb +18 -0
  27. data/lib/coinfresh/model/market.rb +18 -0
  28. data/lib/coinfresh/model/order.rb +22 -0
  29. data/lib/coinfresh/model/trade.rb +18 -0
  30. data/lib/coinfresh/model/wallet.rb +22 -0
  31. data/lib/coinfresh/model/withdraw.rb +21 -0
  32. data/lib/coinfresh/version.rb +3 -0
  33. data/spec/api/cash_flow_spec.rb +23 -0
  34. data/spec/api/currency_spec.rb +24 -0
  35. data/spec/api/market_spec.rb +52 -0
  36. data/spec/api/order_spec.rb +55 -0
  37. data/spec/api/wallet_spec.rb +40 -0
  38. data/spec/api/withdraw_spec.rb +43 -0
  39. data/spec/cassettes/Coinfresh_Api_CashFlow/_list/gets_all_the_cashflows_for_currency.yml +64 -0
  40. data/spec/cassettes/Coinfresh_Api_Currency/_list/gets_all_the_currencies.yml +64 -0
  41. data/spec/cassettes/Coinfresh_Api_Market/_find/gets_a_market_with_the_given_id.yml +64 -0
  42. data/spec/cassettes/Coinfresh_Api_Market/_list/gets_all_the_markets.yml +64 -0
  43. data/spec/cassettes/Coinfresh_Api_Market/_trades/gets_all_trades_for_a_market.yml +64 -0
  44. data/spec/cassettes/Coinfresh_Api_Order/_cancel/cancels_an_order.yml +65 -0
  45. data/spec/cassettes/Coinfresh_Api_Order/_create/creates_an_order.yml +64 -0
  46. data/spec/cassettes/Coinfresh_Api_Order/_list/gets_all_the_orders.yml +67 -0
  47. data/spec/cassettes/Coinfresh_Api_Order/_my/gets_all_the_orders.yml +67 -0
  48. data/spec/cassettes/Coinfresh_Api_Wallet/_create/creates_a_wallet_with_the_given_id.yml +64 -0
  49. data/spec/cassettes/Coinfresh_Api_Wallet/_list/gets_all_the_wallets.yml +64 -0
  50. data/spec/cassettes/Coinfresh_Api_Withdraw/_create/creates_a_wallet_with_the_given_id.yml +64 -0
  51. data/spec/cassettes/Coinfresh_Api_Withdraw/_list/gets_all_the_wallets.yml +64 -0
  52. data/spec/spec_helper.rb +22 -0
  53. data/spec/support/common_let_helpers.rb +62 -0
  54. data/spec/support/json_api_helpers.rb +5 -0
  55. metadata +190 -0
@@ -0,0 +1,106 @@
1
+ require 'api-auth'
2
+
3
+ module Coinfresh
4
+
5
+ module Http
6
+ class Unauthorized < Exception; end
7
+ class ResourceNotFound < Exception; end
8
+ class BadRequest < Exception; end
9
+
10
+ def base_uri(path, params = {})
11
+ uri = URI.parse(self.class.base_scope_url)
12
+ uri.path = path
13
+ uri.query = URI.encode_www_form(params) if params.any?
14
+ uri
15
+ end
16
+
17
+ def get(path, params ={}, parse=true)
18
+ uri = base_uri("#{api_prefix}/#{path}", params)
19
+ req = Net::HTTP::Get.new(uri.request_uri)
20
+ make_api_request(req, uri, parse)
21
+ end
22
+
23
+ def put(path, body = "", parse=true)
24
+ uri = base_uri("#{api_prefix}/#{path}")
25
+ req = Net::HTTP::Put.new(uri.request_uri)
26
+ req.body = body
27
+ req.add_field("Content-Type", "application/json")
28
+ make_api_request(req, uri, parse)
29
+ end
30
+
31
+ def multipart_post(path, params, parse = true)
32
+ uri = base_uri("#{api_prefix}/#{path}")
33
+ req = Net::HTTP::Post::Multipart.new(uri.request_uri, params)
34
+ make_api_request(req, uri, parse)
35
+ end
36
+
37
+ def post(path, body ="", parse = true)
38
+ uri = base_uri("#{api_prefix}/#{path}")
39
+ req = Net::HTTP::Post.new(uri.request_uri)
40
+ req.body = body
41
+ req.add_field("Content-Type", "application/json")
42
+ make_api_request(req, uri, parse)
43
+ end
44
+
45
+ def delete(path, parse=true)
46
+ uri = base_uri("#{api_prefix}/#{path}")
47
+ req = Net::HTTP::Delete.new(uri.request_uri)
48
+ make_api_request(req, uri, parse)
49
+ end
50
+
51
+ def make_api_request(req, uri, parse = true)
52
+ if self.access_token && self.secret_key
53
+ req = ApiAuth.sign!(req, self.access_token, self.secret_key)
54
+ end
55
+ make_request(req, uri, parse)
56
+ end
57
+
58
+ def make_request(req, uri, parse = true)
59
+ req.add_field("Accept", "text/json")
60
+ n = Net::HTTP.new(uri.host, uri.port)
61
+ if uri.scheme == "https"
62
+ n.use_ssl = true
63
+ end
64
+ res = n.start do |http|
65
+ http.request(req)
66
+ end
67
+ parse_response(res, parse)
68
+ end
69
+
70
+ def parse_response(res, parse)
71
+ if res.body !~ /^\s*$/ && !res.body.nil?
72
+ body = parse ? JSON.parse(res.body) : res.body
73
+ end
74
+
75
+ case res
76
+ when Net::HTTPNotFound
77
+ raise Coinfresh::Http::ResourceNotFound.new(body["message"])
78
+ when Net::HTTPSuccess
79
+ body
80
+ when Net::HTTPUnauthorized
81
+ raise Coinfresh::Http::Unauthorized.new(body["message"])
82
+ when Net::HTTPBadRequest
83
+ message = ""
84
+ if body["error"]
85
+ message = [body["error"].to_s, body["message"].to_s].join(" ")
86
+ end
87
+
88
+ if body["errors"]
89
+ message = body["errors"]
90
+ end
91
+
92
+ raise Coinfresh::Http::BadRequest.new(message)
93
+ when Net::HTTPSeeOther
94
+ res["Location"]
95
+ else
96
+ raise "Unknown #{res.class} response. #{body["message"]}"
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def api_prefix; "/api/v1"; end
103
+
104
+ end
105
+
106
+ end
@@ -0,0 +1,175 @@
1
+ module Coinfresh
2
+ module Model
3
+ class ResourceNotSaved < Exception; end
4
+ class AttributeReadOnly < Exception; end
5
+
6
+ class Base
7
+
8
+ attr_accessor :client
9
+
10
+ def self.inspect
11
+ attr_list = attributes.inject([]) do |a, (attr, opts)|
12
+ a << "#{attr}: #{opts[:type]}"
13
+ end * ", "
14
+ "#{super}(#{attr_list})"
15
+ end
16
+
17
+ def inspect
18
+ attr_list = self.class.attributes.inject([]) do |a, (attr, opts)|
19
+ if has_attribute?(attr)
20
+ a << "#{attr}: #{self[attr].inspect}"
21
+ else
22
+ a
23
+ end
24
+ end * ", "
25
+ "#<#{self.class} #{attr_list}>"
26
+ end
27
+
28
+ def initialize(values = {}, client = nil)
29
+ self.client = client
30
+ values.each_pair do |k, v|
31
+ self.send("#{k}=", v) if respond_to?("#{k}=") && !v.nil?
32
+ end
33
+ end
34
+
35
+ def to_params
36
+ self.class.attributes.inject({}) do |h, (attr, opts)|
37
+ has_attribute?(attr) ? h.merge(attr => paramify(self[attr])) : h
38
+ end
39
+ end
40
+
41
+
42
+ class << self
43
+
44
+ attr_accessor :attributes
45
+ def set_attributes(attrs)
46
+ self.attributes = attrs
47
+ attrs.each_pair do |name, options|
48
+ attr_reader name
49
+ define_method "#{name}=" do |value|
50
+ if options[:readonly] && !instance_variable_get("@#{name}").nil?
51
+ raise AttributeReadOnly
52
+ end
53
+ write_attribute("#{name}", convert_attribute(value, options))
54
+ end
55
+ end
56
+ end
57
+
58
+ def inherited(subclass)
59
+ if !self.attributes.nil?
60
+ subclass.attributes = self.attributes
61
+ end
62
+ end
63
+
64
+ def has_association(name, klass, options = {})
65
+ attr_accessor "#{name}_id"
66
+ attr_reader name
67
+ self.attributes["#{name}_id".intern] = {type: :foreign_key}
68
+ define_method "#{name}=" do |attributes|
69
+ write_attribute("#{name}_id", attributes["id"])
70
+ if options[:polymorphic]
71
+ obj = polymorphic_object(attributes, options[:accepted_types])
72
+ else
73
+ obj = klass.new(attributes, client)
74
+ end
75
+ write_attribute("#{name}", obj)
76
+ end
77
+ end
78
+
79
+ def has_many_association(name, klass, options = {})
80
+ attr_reader name
81
+ self.attributes[name.intern] = {type: :has_many_association}
82
+ define_method "#{name}=" do |arr|
83
+ many = arr.collect do |attributes|
84
+ if options[:polymorphic]
85
+ polymorphic_object(attributes, options[:accepted_types])
86
+ else
87
+ klass.new(attributes, client)
88
+ end
89
+ end
90
+ write_attribute(name, many)
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ def ==(o)
97
+ self.class == o.class && !self.id.nil? && self.id != "" && self.id == o.id
98
+ end
99
+ alias_method :eql?, :==
100
+
101
+ def [](val)
102
+ self.send(val)
103
+ end
104
+
105
+
106
+ def save
107
+ if self.id.nil?
108
+ #puts "saving #{self}, #{self.to_params}}"
109
+ item = api.create(self.to_params)
110
+ puts "item: #{item.id}"
111
+ item
112
+ else
113
+ api.update(self.id, self.to_params)
114
+ end
115
+ end
116
+
117
+ def reload
118
+ raise ResourceNotSaved if self.id.nil?
119
+ api.find(self.id)
120
+ end
121
+
122
+ def destroy
123
+ raise ResourceNotSaved if self.id.nil?
124
+ api.destroy(self.id)
125
+ end
126
+
127
+ private
128
+ def write_attribute(name, value)
129
+ instance_variable_set("@#{name}", value)
130
+ end
131
+
132
+ def api
133
+ raise NotImplementedError
134
+ end
135
+
136
+ def has_attribute?(attr)
137
+ instance_variable_defined?("@#{attr}")
138
+ end
139
+
140
+ def paramify(val)
141
+ if val.kind_of? Coinfresh::Model::Base
142
+ val.to_params
143
+ elsif val.kind_of? Array
144
+ val.collect{|v| paramify(v) }
145
+ else
146
+ val
147
+ end
148
+ end
149
+
150
+ def convert_attribute(val, options)
151
+ case options[:type]
152
+ when :int
153
+ val.to_i
154
+ when :string
155
+ val.to_s
156
+ when :date
157
+ val.kind_of?(Date) ? val : Date.parse(val)
158
+ when :decimal
159
+ val.to_f
160
+ when :boolean
161
+ val == "true"
162
+ when :datetime
163
+ val.kind_of?(DateTime) ? val : DateTime.parse(val)
164
+ when :datetime
165
+ val.kind_of?(Time) ? val : Time.parse(val)
166
+ when :foreign_key
167
+ (val == "" || val.nil?) ? nil : val.to_i
168
+ else
169
+ val
170
+ end
171
+ end
172
+
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,17 @@
1
+ module Coinfresh
2
+ module Model
3
+ class CashFlow < Base
4
+ set_attributes(id: {type: :int, readonly: true},
5
+ created_at: {type: :datetime, readonly: true},
6
+ cash_type: {type: :string, readonly: true},
7
+ amount: {type: :decimal, readonly: true}
8
+ )
9
+
10
+ private
11
+ def api
12
+ client.cash_flows
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module Coinfresh
2
+ module Model
3
+ class Currency < Base
4
+ set_attributes(id: {type: :int, readonly: true},
5
+ name: {type: :string, readonly: true},
6
+ ticker: {type: :string, readonly: true},
7
+ withdraw_transaction_fee: {type: :decimal, readonly: true},
8
+ deposit_confirmations: {type: :int, readonly: true}
9
+ )
10
+
11
+ private
12
+ def api
13
+ client.currencies
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Coinfresh
2
+ module Model
3
+ class Market < Base
4
+ set_attributes(id: {type: :int, readonly: true},
5
+ name: {type: :string, readonly: true},
6
+ last_price: {type: :decimal, readonly: true}
7
+ )
8
+
9
+ has_association :base_currency, Coinfresh::Model::Currency
10
+ has_association :currency, Coinfresh::Model::Currency
11
+
12
+ private
13
+ def api
14
+ client.markets
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ module Coinfresh
2
+ module Model
3
+ class Order < Base
4
+ set_attributes(id: {type: :int, readonly: true},
5
+ created_at: {type: :datetime, readonly: true},
6
+ updated_at: {type: :datetime, readonly: true},
7
+ filled_amount: {type: :decimal, readonly: true},
8
+ status: {type: :string},
9
+ order_type: {type: :string},
10
+ amount: {type: :decimal},
11
+ price: {type: :decimal},
12
+ market_id: {type: :integer}
13
+ )
14
+
15
+ private
16
+ def api
17
+ client.orders
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ module Coinfresh
2
+ module Model
3
+ class Trade < Base
4
+ set_attributes(id: {type: :int, readonly: true},
5
+ created_at: {type: :datetime, readonly: true},
6
+ amount: {type: :decimal, readonly: true},
7
+ price: {type: :decimal, readonly: true},
8
+ buy_order_id: {type: :int, readonly: true},
9
+ sell_order_id: {type: :int, readonly: true}
10
+ )
11
+
12
+ private
13
+ def api
14
+ client.markets
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ module Coinfresh
2
+ module Model
3
+ class Wallet < Base
4
+ set_attributes(id: {type: :int, readonly: true},
5
+ balance: {type: :decimal, readonly: true},
6
+ deposit_address: {type: :string, readonly: true},
7
+ in_escrow: {type: :decimal, readonly: true},
8
+ total_withdraw: {type: :decimal, readonly: true},
9
+ total_deposit: {type: :decimal, readonly: true},
10
+ unconfirmed_deposit: {type: :decimal, readonly: true},
11
+ )
12
+
13
+ has_association :currency, Coinfresh::Model::Currency
14
+
15
+ private
16
+ def api
17
+ client.wallets
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ module Coinfresh
2
+ module Model
3
+ class Withdraw < Base
4
+ set_attributes(id: {type: :int, readonly: true},
5
+ created_at: {type: :datetime, readonly: true},
6
+ address: {type: :string, readonly: true},
7
+ amount: {type: :decimal, readonly: true},
8
+ txid: {type: :string, readonly: true},
9
+ status: {type: :string, readonly: true},
10
+ )
11
+
12
+ has_association :wallet, Coinfresh::Model::Wallet
13
+
14
+ private
15
+ def api
16
+ client.withdraws
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module Coinfresh
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ module Coinfresh
4
+ module Api
5
+ describe CashFlow, :vcr do
6
+
7
+ describe "#list" do
8
+ it "gets all the cashflows for currency" do
9
+ cash_flows = client.cash_flows.list(limit: 2, currency: 'BTC')
10
+ expect(cash_flows.count).to be > 0
11
+ cash_flow = cash_flows.first
12
+ expect(cash_flow.id).not_to be_nil
13
+ expect(cash_flow.created_at).not_to be_nil
14
+ expect(cash_flow.amount).not_to be_nil
15
+ expect(cash_flow.cash_type).not_to be_nil
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end