vexapion 0.3.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 13b088be62d4de49b5f471088077d2c0142e0fa8
4
+ data.tar.gz: 130e8e80c10272e6ff2a48c18c84f3a4516e7211
5
+ SHA512:
6
+ metadata.gz: 3433e525af5857b92594d294fdb6e44c7dcd134f44ffaa718dddf6be58bfe0d16e22bfa9a2705d052c0344e66bac6e291cf2283e1aaff82902412739b6dbaf06
7
+ data.tar.gz: a42752f44c429d38b3bcf3428132f41cff7d7673c6096ad0dc602ce475c0b65b78410e4595446b948027b566512b9609978a4035d050d457d696bc2cfb2d0c8f
@@ -0,0 +1,66 @@
1
+ # coding: utf-8
2
+
3
+ module Vexapion
4
+
5
+ # Virtual (crypto) Currency Exchanges API wrapper class
6
+
7
+ class BaseExchanges
8
+
9
+ def initialize(key = nil, secret = nil)
10
+ @key = key
11
+ @secret = secret
12
+ @conn = HTTPClient.new
13
+ base_time = Time.gm(2017, 1, 1, 0, 0, 0).to_i
14
+ @nonce = (Time.now.to_i - base_time) * 100 #max 100req/s
15
+ @verify_mode = nil
16
+ set_min_interval(0.5)
17
+ end
18
+
19
+ def set_min_interval(sec)
20
+ @conn.min_interval = sec
21
+ end
22
+
23
+ def set_verify_mode(mode)
24
+ @verify_mode = mode
25
+ end
26
+
27
+ def do_command(uri, request)
28
+ response = nil
29
+ begin
30
+ response = @conn.http_request(uri, request, @verify_mode)
31
+ rescue VexapionRuntimeError => e
32
+ raise e
33
+ rescue HTTPError => e
34
+ raise e
35
+ end
36
+
37
+ response == '' ? '' : JSON.parse(response)
38
+ end
39
+
40
+ def get_nonce
41
+ @nonce += 1
42
+ end
43
+
44
+ def error_check(res)
45
+ if res != nil && res != '' && res.kind_of?(Hash)
46
+
47
+ if res['success'] == 0 || res['success'] == 'false'
48
+ #polo
49
+ fail RequestFailed.new(
50
+ false, false, res)
51
+ elsif res.has_key?('error')
52
+ #zaif, polo
53
+ fail RequestFailed.new(
54
+ false, res['error'], res)
55
+ elsif res.has_key?('error_message')
56
+ #bitflyer
57
+ fail RequestFailed.new(
58
+ false, "#{res['status']} #{res['error_message']}", res)
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ end #of class
65
+
66
+ end #of Vexapion module
@@ -0,0 +1,353 @@
1
+ # coding: utf-8
2
+
3
+ require 'vexapion'
4
+
5
+ module Vexapion
6
+
7
+ # bitflyerのAPIラッパークラスです
8
+ # 各メソッドの戻り値は下記URLを参照してください
9
+ # @see https://lightning.bitflyer.jp/docs?lang=ja&_ga=1.264432847.170149243.1463313992
10
+
11
+ class Bitflyer < BaseExchanges
12
+
13
+ def initialize(key = nil, secret = nil)
14
+ super(key, secret)
15
+
16
+ @public_url = 'https://api.bitflyer.jp/v1/'
17
+ @private_url = 'https://api.bitflyer.jp/v1/me/'
18
+
19
+ set_min_interval(0.3)
20
+
21
+ @available_pair = ['BTC_JPY', 'FX_BTC_JPY', 'ETH_BTC']
22
+ end
23
+
24
+ # Public API
25
+ #板情報
26
+ def board(pair)
27
+ public_get('board', product_code: pair.upcase)
28
+ end
29
+ alias get_board board
30
+
31
+ #Ticker
32
+ def ticker(pair)
33
+ public_get('ticker', product_code: pair.upcase)
34
+ end
35
+ alias get_ticker ticker
36
+
37
+ #約定履歴
38
+ def executions(pair, count='', before='', after='')
39
+ params = {
40
+ product_code: pair.upcase
41
+ }
42
+ params[:count] = count if count != ''
43
+ params[:before] = before if before != ''
44
+ params[:after] = after if after != ''
45
+ public_get('executions', params)
46
+ end
47
+ #get_executionsは個人の約定履歴の取得に使っているので混同しないこと
48
+ alias get_public_executions executions
49
+
50
+ #チャット
51
+ def get_chats(date)
52
+ public_get('getchats', from_date: date)
53
+ end
54
+
55
+ #取引所の状態
56
+ def get_health
57
+ public_get('gethealth')
58
+ end
59
+
60
+ # Private API
61
+ #APIキーの権限を取得
62
+ def get_permissions
63
+ get('getpermissions')
64
+ end
65
+
66
+ #資産残高を取得
67
+ def get_balance
68
+ get('getbalance')
69
+ end
70
+
71
+ #証拠金の状態を取得
72
+ def get_collateral
73
+ get('getcollateral')
74
+ end
75
+
76
+ #預入用BTC/ETHアドレス取得
77
+ def get_addresses
78
+ get('getaddresses')
79
+ end
80
+
81
+ #BTC/ETH預入履歴
82
+ def get_coin_ins(count='', before='', after='')
83
+ params = Hash.new
84
+ params[:count] = count if count != ''
85
+ params[:before] = before if before != ''
86
+ params[:after] = after if after != ''
87
+ get('getcoinins', params)
88
+ end
89
+
90
+ #BTC/ETH外部送付
91
+ def sendcoin(currency, amount, address, fee='', code='')
92
+ params = {
93
+ currency_code: currency.upcase,
94
+ amount: amount.to_f,
95
+ address: address,
96
+ }
97
+ if fee != ''
98
+ fee = 0.0005 < fee.to_f ? 0.0005 : fee.to_f
99
+ params[:additional_fee] = fee
100
+ end
101
+ params[:code] = code.to_i if code != ''
102
+
103
+ post('sendcoin', params)
104
+ end
105
+
106
+ #BTC/ETH送付履歴
107
+ def get_coin_outs(count='', before='', after='')
108
+ params = Hash.new
109
+ #params[:message_id] = id if id != ''
110
+ params[:count] = count if count != ''
111
+ params[:before] = before if before != ''
112
+ params[:after] = after if after != ''
113
+
114
+ get('getcoinouts', params)
115
+ end
116
+
117
+ #BTC/ETH送付状況確認
118
+ # @params [String] message_id sendcoinAPIの戻り値を指定
119
+ # @return [hash]
120
+ def get_coin_outs_id(message_id)
121
+ params = { message_id: message_id }
122
+
123
+ get('getcoinouts', params)
124
+ end
125
+
126
+ #銀行口座一覧取得
127
+ def get_bank_accounts
128
+ get('getbankaccounts')
129
+ end
130
+
131
+ #デポジット入金履歴
132
+ def get_deposits(count='', before='', after='')
133
+ params = Hash.new
134
+ params[:count] = count if count != ''
135
+ params[:before] = before if before != ''
136
+ params[:after] = after if after != ''
137
+
138
+ get('getdeposits', params)
139
+ end
140
+
141
+ #デポジット解約(出金)
142
+ def withdraw(currency, id, amount, code='')
143
+ params = {
144
+ currency_code: currency.upcase,
145
+ bank_account_id: id,
146
+ amount: amount
147
+ }
148
+ params[:code] = code if code != ''
149
+
150
+ post('withdraw', params)
151
+ end
152
+
153
+ #デポジット解約履歴(出金)
154
+ def get_withdrawals(count='', before='', after='')
155
+ params = Hash.new
156
+ params[:count] = count if count != ''
157
+ params[:before] = before if before != ''
158
+ params[:after] = after if after != ''
159
+
160
+ get('getwithdrawals', params)
161
+ end
162
+
163
+
164
+ #新規注文を出す
165
+ def send_child_order(pair, type, side, price, size, expire='', force='')
166
+ params = {
167
+ product_code: pair.upcase,
168
+ child_order_type: type.upcase,
169
+ side: side.upcase,
170
+ price: price,
171
+ size: size.to_f
172
+ }
173
+ params[:minute_to_expire] = expire if expire != ''
174
+ params[:time_in_force] = force if force != ''
175
+
176
+ post('sendchildorder', params)
177
+ end
178
+
179
+ #child_order_idを指定して、注文をキャンセルする
180
+ def cancel_child_order(pair, order_id)
181
+ params = {
182
+ product_code: pair.upcase,
183
+ child_order_id: order_id
184
+ }
185
+
186
+ post('cancelchildorder', params)
187
+ end
188
+
189
+ #child_order_acceptance_idを指定して、注文をキャンセルする
190
+ def cancel_child_order_specify_acceptance_id(pair, acceptance_id)
191
+ params = {
192
+ product_code: pair.upcase,
193
+ child_order_acceptance_id: acceptance_id
194
+ }
195
+
196
+ post('cancelchildorder', params)
197
+ end
198
+
199
+ #新規の親注文を出す(特殊注文)
200
+ #https://lightning.bitflyer.jp/docs/specialorder を熟読して使用のこと
201
+ #とても自由度が高いため、ユーザーがパラメータを組み立ててそれを引数にする
202
+ #def send_parent_order(params)
203
+ # post('sendparentorder', params)
204
+ #end
205
+
206
+ #parent_order_idを指定して、親注文をキャンセルする
207
+ #def cancel_parent_order(pair, order_id)
208
+ # params = {
209
+ # product_code: pair.upcase,
210
+ # parent_order_id: order_id
211
+ # }
212
+
213
+ # post('cancelparentorder', params)
214
+ #end
215
+
216
+ #parent_order_acceptance_idを指定して、親注文をキャンセルする
217
+ #def cancel_parent_order_specify_acceptance_id(pair, acceptance_id)
218
+ # params = {
219
+ # product_code: pair.upcase,
220
+ # parent_order_acceptance_id: acceptance_id
221
+ # }
222
+ # post('cancelparentorder', params)
223
+ #end
224
+
225
+ #すべての注文をキャンセルする
226
+ def cancel_all_child_order(pair)
227
+ post('cancelallchildorders', product_code: pair.upcase)
228
+ end
229
+
230
+ #注文の一覧を取得
231
+ def get_child_orders(pair, state='', pid='', count='', before='', after='')
232
+ params = {
233
+ product_code: pair.upcase
234
+ }
235
+ params[:child_order_state] = state if state != ''
236
+ params[:parent_order_id] = pid if pid != ''
237
+ params[:count] = count if count != ''
238
+ params[:before] = before if before != ''
239
+ params[:after] = after if after != ''
240
+
241
+ get('getchildorders', params)
242
+ end
243
+
244
+ #親注文の一覧を取得
245
+ #def get_parent_orders(pair, state='', count='', before='', after='')
246
+ # params = {
247
+ # product_code: pair.upcase
248
+ # }
249
+ # params[:parent_order_state] = state if state != ''
250
+ # params[:count] = count if count != ''
251
+ # params[:before] = before if before != ''
252
+ # params[:after] = after if after != ''
253
+
254
+ # get('getparentorders', params)
255
+ #end
256
+
257
+ #parent_order_idを指定して、親注文の詳細を取得
258
+ #def get_parent_order(parent_order_id)
259
+ # get('getparentorder', parent_order_id: parent_order_id)
260
+ #end
261
+
262
+ #parent_order_acceptance_idを指定して、親注文の詳細を取得
263
+ #def get_parent_order_specify_acceptance_id(acceptance_id)
264
+ # get('getparentorder', parent_order_acceptance_id: acceptance_id)
265
+ #end
266
+
267
+ #約定の一覧を取得
268
+ def get_executions(pair, coid='', child_order_acceptance_id='',
269
+ count='', before='', after='')
270
+ params = {
271
+ product_code: pair.upcase
272
+ }
273
+ params['child_order_id'] = coid if coid != ''
274
+ if child_order_acceptance_id != ''
275
+ params['child_order_acceptance_id'] = child_order_acceptance_id
276
+ end
277
+ params[:count] = count if count != ''
278
+ params[:before] = before if before != ''
279
+ params[:after] = after if after != ''
280
+
281
+ get('getexecutions', params)
282
+ end
283
+
284
+ #建玉の一覧を取得
285
+ def get_positions(pair='FX_BTC_JPY')
286
+ get('getpositions', product_code: pair.upcase)
287
+ end
288
+
289
+
290
+ # Create request header & body
291
+
292
+ private
293
+
294
+ def public_get(command, query={})
295
+ uri = URI.parse "#{@public_url}#{command}"
296
+ uri.query = URI.encode_www_form(query)
297
+ request = Net::HTTP::Get.new(uri.request_uri)
298
+ request.set_form_data(query) #クエリをURLエンコード(p1=v1&p2=v2...)
299
+
300
+ do_command(uri, request)
301
+ end
302
+
303
+ def get(command, query={})
304
+ method = 'GET'
305
+ uri = URI.parse "#{@private_url}#{command}"
306
+ uri.query = URI.encode_www_form(query) if query != {}
307
+ timestamp = get_nonce.to_s
308
+ text = "#{timestamp}#{method}#{uri.request_uri}"
309
+ sign = signature(text)
310
+ header = {
311
+ 'ACCESS-KEY' => @key,
312
+ 'ACCESS-TIMESTAMP' => timestamp,
313
+ 'ACCESS-SIGN' => sign
314
+ }
315
+
316
+ request = Net::HTTP::Get.new(uri.request_uri, initheader = header)
317
+
318
+ do_command(uri, request)
319
+ end
320
+
321
+ def post(command, params={})
322
+ method = 'POST'
323
+ uri = URI.parse "#{@private_url}#{command}"
324
+ timestamp = get_nonce.to_s
325
+ body = params.to_json #add
326
+
327
+ text = "#{timestamp}#{method}#{uri.request_uri}#{body}"
328
+ sign = signature(text)
329
+ header = headers(sign, timestamp)
330
+ request = Net::HTTP::Post.new(uri.request_uri, initheader = header)
331
+ request.body = body
332
+
333
+ res = do_command(uri, request)
334
+ error_check(res)
335
+ res
336
+ end
337
+
338
+ def signature(data)
339
+ algo = OpenSSL::Digest.new('sha256')
340
+ OpenSSL::HMAC.hexdigest(algo, @secret, data)
341
+ end
342
+
343
+ def headers(sign, timestamp)
344
+ headers = {
345
+ 'ACCESS-KEY' => @key,
346
+ 'ACCESS-TIMESTAMP' => timestamp,
347
+ 'ACCESS-SIGN' => sign,
348
+ 'Content-Type' => 'application/json'
349
+ }
350
+ end
351
+
352
+ end #of class
353
+ end #of module