andrewroth-btce 0.1.9.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 (2) hide show
  1. data/lib/btce.rb +295 -0
  2. metadata +82 -0
data/lib/btce.rb ADDED
@@ -0,0 +1,295 @@
1
+ # Copyright (c) 2013, Christopher Mark Gore,
2
+ # Soli Deo Gloria,
3
+ # All rights reserved.
4
+ #
5
+ # 8729 Lower Marine Road, Saint Jacob, Illinois 62281 USA.
6
+ # Web: http://cgore.com
7
+ # Email: cgore@cgore.com
8
+ #
9
+ # Redistribution and use in source and binary forms, with or without
10
+ # modification, are permitted provided that the following conditions are met:
11
+ #
12
+ # * Redistributions of source code must retain the above copyright
13
+ # notice, this list of conditions and the following disclaimer.
14
+ #
15
+ # * Redistributions in binary form must reproduce the above copyright
16
+ # notice, this list of conditions and the following disclaimer in the
17
+ # documentation and/or other materials provided with the distribution.
18
+ #
19
+ # * Neither the name of Christopher Mark Gore nor the names of other
20
+ # contributors may be used to endorse or promote products derived from
21
+ # this software without specific prior written permission.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ # POSSIBILITY OF SUCH DAMAGE.
34
+
35
+ require 'json'
36
+ require 'monkey-patch'
37
+ require 'net/http'
38
+ require 'net/https'
39
+ require 'openssl'
40
+ require 'uri'
41
+ require 'yaml'
42
+ require 'cgi'
43
+
44
+
45
+ module Btce
46
+ class API
47
+ BTCE_DOMAIN = "btc-e.com"
48
+ CURRENCIES = %w(btc
49
+ usd
50
+ rur
51
+ ltc
52
+ nmc
53
+ eur
54
+ nvc
55
+ trc
56
+ ppc
57
+ fnc)
58
+ CURRENCY_PAIRS = %w(btc_usd
59
+ btc_eur
60
+ btc_rur
61
+ ltc_btc
62
+ ltc_usd
63
+ ltc_rur
64
+ nmc_btc
65
+ usd_rur
66
+ eur_usd
67
+ nvc_btc
68
+ trc_btc
69
+ ppc_btc
70
+ ftc_btc)
71
+ MAX_DIGITS = {
72
+ "btc_usd" => 3,
73
+ "btc_eur" => 3,
74
+ "btc_rur" => 4,
75
+ "ltc_btc" => 5,
76
+ "ltc_usd" => 6,
77
+ "ltc_rur" => 4,
78
+ "nmc_btc" => 4,
79
+ "usd_rur" => 4,
80
+ "eur_usd" => 4,
81
+ "nvc_btc" => 4,
82
+ "trc_btc" => 4,
83
+ "ppc_btc" => 4,
84
+ "ftc_btc" => 4
85
+ }
86
+ KEY = YAML::load File.open 'btce-api-key.yml'
87
+
88
+ class << self
89
+ def get_https(url, params = nil, sign = nil)
90
+ raise ArgumentError if not url.is_a? String
91
+ uri = URI.parse url
92
+ http = Net::HTTP.new uri.host, uri.port
93
+ http.use_ssl = true
94
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
95
+ if params.nil?
96
+ request = Net::HTTP::Get.new uri.request_uri
97
+ else
98
+ # If sending params, then we want a post request for authentication.
99
+ request = Net::HTTP::Post.new uri.request_uri
100
+ request.add_field "Key", API::KEY['key']
101
+ request.add_field "Sign", sign
102
+ request.set_form_data params
103
+ end
104
+ response = http.request request
105
+ response.body
106
+ end
107
+
108
+ def get_json(url, params = nil, sign = nil)
109
+ result = get_https(url, params, sign)
110
+ if not result.is_a? String or not result.valid_json?
111
+ raise RuntimeError, "Server returned invalid data."
112
+ end
113
+ JSON.load result
114
+ end
115
+ end
116
+ end
117
+
118
+ class PublicAPI < API
119
+ OPERATIONS = %w(fee ticker trades depth)
120
+
121
+ class << self
122
+
123
+ def get_pair_operation_json(pair, operation)
124
+ raise ArgumentError if not API::CURRENCY_PAIRS.include? pair
125
+ raise ArgumentError if not OPERATIONS.include? operation
126
+ get_json "https://#{API::BTCE_DOMAIN}/api/2/#{pair}/#{operation}"
127
+ end
128
+
129
+ OPERATIONS.each do |operation|
130
+ class_eval %{
131
+ def get_pair_#{operation}_json(pair)
132
+ get_pair_operation_json pair, "#{operation}"
133
+ end
134
+ }
135
+
136
+ API::CURRENCY_PAIRS.each do |pair|
137
+ class_eval %{
138
+ def get_#{pair}_#{operation}_json
139
+ get_pair_#{operation}_json "#{pair}"
140
+ end
141
+ }
142
+ end
143
+ end
144
+ end
145
+ end
146
+
147
+ class PublicOperation
148
+ attr_reader :json, :operation, :pair
149
+
150
+ def initialize(operation, pair)
151
+ @operation = operation
152
+ @pair = pair
153
+ load_json
154
+ end
155
+
156
+ def load_json
157
+ @json = PublicAPI.get_pair_operation_json pair, operation
158
+ end
159
+ end
160
+
161
+ class Fee < PublicOperation
162
+ def initialize(pair)
163
+ super 'fee', pair
164
+ end
165
+
166
+ def trade
167
+ json["trade"]
168
+ end
169
+ end
170
+
171
+ class Ticker < PublicOperation
172
+ def initialize(pair)
173
+ super 'ticker', pair
174
+ end
175
+
176
+ JSON_METHODS = %w(high low avg vol vol_cur last buy sell server_time)
177
+
178
+ JSON_METHODS.each do |method|
179
+ class_eval %{
180
+ def #{method}
181
+ json["ticker"]["#{method}"] if json["ticker"] and json["ticker"].is_a? Hash
182
+ end
183
+ }
184
+ end
185
+
186
+ alias_method :bid, :buy
187
+ alias_method :offer, :sell
188
+ alias_method :ask, :sell
189
+ alias_method :average, :avg
190
+ alias_method :volume, :vol
191
+ alias_method :volume_current, :vol_cur
192
+
193
+ def spread
194
+ (offer - bid) / offer
195
+ end
196
+
197
+ def spread_percent
198
+ spread * 100.0
199
+ end
200
+ end
201
+
202
+ class Trade
203
+ attr_accessor :json
204
+
205
+ JSON_METHODS = %w(date price amount tid price_currency item trade_type)
206
+
207
+ attr_accessor *JSON_METHODS.map(&:to_sym)
208
+
209
+ class << self
210
+ def new_from_json(json)
211
+ result = Trade.new
212
+ result.json = json
213
+ if json.is_a? Hash
214
+ JSON_METHODS.each do |method|
215
+ instance_eval %{
216
+ result.#{method} = json["#{method}"]
217
+ }
218
+ end
219
+ end
220
+ result
221
+ end
222
+ end
223
+ end
224
+
225
+ class Trades < PublicOperation
226
+ attr_reader :all
227
+
228
+ def initialize(pair)
229
+ super 'trades', pair
230
+ load_trades
231
+ end
232
+
233
+ def load_trades
234
+ @all = json.map {|trade| Trade.new_from_json trade} if json.is_a? Array
235
+ end
236
+ private :load_trades
237
+
238
+ def [] *rest
239
+ all[*rest]
240
+ end
241
+ end
242
+
243
+ class Depth < PublicOperation
244
+ def initialize(pair)
245
+ super 'depth', pair
246
+ end
247
+ end
248
+
249
+ class TradeAPI < API
250
+ OPERATIONS = %w(getInfo
251
+ TransHistory
252
+ TradeHistory
253
+ OrderList
254
+ Trade
255
+ CancelOrder)
256
+
257
+ class << self
258
+ def sign(params)
259
+ data = params.collect do |key, value|
260
+ "#{key}=#{CGI::escape(value.to_s)}"
261
+ end.join('&')
262
+
263
+ # Sign data with the HMAC SHA-512 algorhythm
264
+ # Read https://btc-e.com/defines/documentation
265
+ OpenSSL::HMAC.hexdigest('sha512', API::KEY['secret'], data)
266
+ end
267
+
268
+ def trade_api_call(method, extra)
269
+ params = {"method" => method, "nonce" => nonce}
270
+ if ! extra.empty?
271
+ extra.each do |k,v|
272
+ params[k.to_s] = v
273
+ end
274
+ end
275
+ signed = sign params
276
+ get_json "https://#{API::BTCE_DOMAIN}/tapi", params, signed
277
+ end
278
+
279
+ def nonce
280
+ @nonce = 0 if @nonce.nil?
281
+ @nonce += 1
282
+ Time::now.to_i + @nonce
283
+ end
284
+ private :nonce
285
+
286
+ OPERATIONS.each do |operation|
287
+ class_eval %{
288
+ def #{operation.camelcase_to_snakecase} extra={}
289
+ trade_api_call "#{operation}", extra
290
+ end
291
+ }
292
+ end
293
+ end
294
+ end
295
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: andrewroth-btce
3
+ version: !ruby/object:Gem::Version
4
+ hash: 97
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 9
10
+ - 1
11
+ version: 0.1.9.1
12
+ platform: ruby
13
+ authors:
14
+ - Christopher Mark Gore
15
+ - Andrew Roth
16
+ autorequire:
17
+ bindir: bin
18
+ cert_chain: []
19
+
20
+ date: 2013-07-26 00:00:00 -04:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ name: monkey-patch
25
+ prerelease: false
26
+ requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ hash: 3
32
+ segments:
33
+ - 0
34
+ version: "0"
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: A simple library to interface with the API for btc-e.com in Ruby.
38
+ email: andrewroth@gmail.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - lib/btce.rb
47
+ has_rdoc: true
48
+ homepage: https://github.com/cgore/ruby-btce
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.5.3
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: A simple library to interface with the API for btc-e.com in Ruby.
81
+ test_files: []
82
+