coinbase-exchange 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 452c6b81858eaeb6b32e7369818b2c817431c106
4
+ data.tar.gz: dc3749525c0da9a50267c22af9056e8f3b29315a
5
+ SHA512:
6
+ metadata.gz: c67ab3066726b7b256a054b818399f78ea3a99d9a818ad48c419ed1a3c688a6b77b9dff901e7ef80fc38c73dce231083416c22d689b28e11cfe7639488476c01
7
+ data.tar.gz: 33c151064d84f905d0290c6a697ddd0e87712662d7236819a6334b10acbe2a979bae8e6a9090c0df10e07bab0c5cc8c534735c4eeb1450cfbf7837baa443e441
@@ -0,0 +1 @@
1
+ *.gem
@@ -0,0 +1,21 @@
1
+ AllCops:
2
+ Exclude:
3
+ - '*.gemspec'
4
+
5
+ Style/StringLiterals:
6
+ Enabled: false
7
+ Style/SpaceInsideBrackets:
8
+ Enabled: false
9
+ Style/TrivialAccessors:
10
+ Enabled: false
11
+
12
+ Metrics/LineLength:
13
+ Max: 120
14
+ Metrics/MethodLength:
15
+ Max: 50
16
+ Metrics/ClassLength:
17
+ Enabled: false
18
+ Metrics/AbcSize:
19
+ Max: 50
20
+ Metrics/CyclomaticComplexity:
21
+ Max: 15
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in coinbase-exchange.gemspec
4
+ gemspec
@@ -0,0 +1,72 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ coinbase-exchange (0.1.1)
5
+ bigdecimal
6
+ em-http-request
7
+ faye-websocket
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.3.8)
13
+ bigdecimal (1.2.7)
14
+ coderay (1.1.0)
15
+ cookiejar (0.3.2)
16
+ crack (0.4.2)
17
+ safe_yaml (~> 1.0.0)
18
+ diff-lcs (1.2.5)
19
+ em-http-request (1.1.2)
20
+ addressable (>= 2.3.4)
21
+ cookiejar
22
+ em-socksify (>= 0.3)
23
+ eventmachine (>= 1.0.3)
24
+ http_parser.rb (>= 0.6.0)
25
+ em-socksify (0.3.0)
26
+ eventmachine (>= 1.0.0.beta.4)
27
+ eventmachine (1.0.7)
28
+ faye-websocket (0.9.2)
29
+ eventmachine (>= 0.12.0)
30
+ websocket-driver (>= 0.5.1)
31
+ http_parser.rb (0.6.0)
32
+ method_source (0.8.2)
33
+ pry (0.10.1)
34
+ coderay (~> 1.1.0)
35
+ method_source (~> 0.8.1)
36
+ slop (~> 3.4)
37
+ rake (10.4.2)
38
+ rspec (3.2.0)
39
+ rspec-core (~> 3.2.0)
40
+ rspec-expectations (~> 3.2.0)
41
+ rspec-mocks (~> 3.2.0)
42
+ rspec-core (3.2.3)
43
+ rspec-support (~> 3.2.0)
44
+ rspec-expectations (3.2.1)
45
+ diff-lcs (>= 1.2.0, < 2.0)
46
+ rspec-support (~> 3.2.0)
47
+ rspec-mocks (3.2.1)
48
+ diff-lcs (>= 1.2.0, < 2.0)
49
+ rspec-support (~> 3.2.0)
50
+ rspec-support (3.2.2)
51
+ safe_yaml (1.0.4)
52
+ slop (3.6.0)
53
+ webmock (1.21.0)
54
+ addressable (>= 2.3.6)
55
+ crack (>= 0.3.2)
56
+ websocket-driver (0.5.4)
57
+ websocket-extensions (>= 0.1.0)
58
+ websocket-extensions (0.1.2)
59
+
60
+ PLATFORMS
61
+ ruby
62
+
63
+ DEPENDENCIES
64
+ bundler (~> 1.8)
65
+ coinbase-exchange!
66
+ pry
67
+ rake (~> 10.0)
68
+ rspec
69
+ webmock
70
+
71
+ BUNDLED WITH
72
+ 1.10.3
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 John Duhamel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,446 @@
1
+ # Coinbase Exchange Gem
2
+
3
+ ## REST Client
4
+
5
+ We provide an exchange client that is a thin wrapper over the exchange API. The purpose of this Readme is to provide context for using the gem effectively. For a detailed overview of the information that's available through the API, we recommend consulting the official documentation.
6
+ * https://docs.exchange.coinbase.com/#api
7
+
8
+ We provide a synchronous and asynchronous client. The only functional difference between the two clients is that the asynchronous client must be started inside the Eventmachine reactor loop.
9
+
10
+ **Sychronous Client**
11
+
12
+ ```ruby
13
+ require 'coinbase/exchange'
14
+
15
+ rest_api = Coinbase::Exchange::Client.new(api_key, api_secret, api_pass)
16
+ while true
17
+ sleep 10
18
+ rest_api.last_trade("BTC-GBP") do |resp|
19
+ p "Spot Rate: £ %.2f" % resp.price
20
+ end
21
+ end
22
+ ```
23
+
24
+ **Asynchronous Client**
25
+
26
+ ```ruby
27
+ require 'coinbase/exchange'
28
+ require 'eventmachine'
29
+
30
+ rest_api = Coinbase::Exchange::AsyncClient.new(api_key, api_secret, api_pass)
31
+ EM.run {
32
+ EM.add_periodic_timer(10) {
33
+ rest_api.last_trade("BTC-GBP") do |resp|
34
+ p "Spot Rate: £ %.2f" % resp.price
35
+ end
36
+ }
37
+ }
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ### Initialization
43
+
44
+ To initialize the client, simply pass in an API Key, API Secret, and API Passphrase which you generate on the web interface:
45
+ * https://exchange.coinbase.com/settings
46
+
47
+ ```ruby
48
+ rest_api = Coinbase::Exchange::Client.new(api_key, api_secret, api_pass)
49
+ ```
50
+
51
+ ```ruby
52
+ rest_api = Coinbase::Exchange::AsyncClient.new(api_key, api_secret, api_pass)
53
+ ```
54
+
55
+ **Default Product**
56
+
57
+ Coinbase supports trading bitcoin in several currencies. If you wish to trade a different currency, you can specify an alterative default currency.
58
+
59
+ ```ruby
60
+ gbp_client = Coinbase::Exchange::Client.new(api_key, api_secret, api_pass,
61
+ product_id: "BTC-GBP")
62
+ ```
63
+
64
+ **Sandbox**
65
+
66
+ You can initialize a connection to the sandbox by specifying an alternative api endpoint.
67
+
68
+ ```ruby
69
+ sandbox = Coinbase::Exchange::Client.new(api_key, api_secret, api_pass,
70
+ api_url: "https://api-public.sandbox.exchange.coinbase.com")
71
+ ```
72
+
73
+ ### Methods
74
+
75
+ The default representation of return data is an unmodified hash from the JSON blob returned in the body of the API response. The response should be accessed in a block like this.
76
+
77
+ ```ruby
78
+ rest_api.last_trade do |resp|
79
+ p "Spot Rate: $ %.2f" % BigDecimal(resp['price'])
80
+ end
81
+ ```
82
+
83
+ Note, the synchronous client will also return the same data. However, this is discouraged since it will make porting code to an asynchronous client more difficult. Here is an example of what that might look like.
84
+
85
+ ```ruby
86
+ resp = rest_api.last_trade
87
+ p "Spot Rate: $ %.2f" % BigDecimal(resp['price'])
88
+ ```
89
+
90
+ ### Parameters
91
+
92
+ The gem will automatically encode any additional parameters you pass to method calls. For instance to get the full orderbook, you must explicitly set the level parameter to 3.
93
+
94
+ ```ruby
95
+ rest_api.orderbook('BTC-GBP', level: 3) do |resp|
96
+ p "There are #{resp['bids'].count} open bids on the orderbook"
97
+ p "There are #{resp['asks'].count} open asks on the orderbook"
98
+ end
99
+ ```
100
+
101
+ ### Return Values
102
+
103
+ Data format is a sensitive issue when writing financial software. The exchange API represents monetary data in string format. This is a good intermediary data format for the user to apply their own data format, but is not escpecially useful on its own.
104
+
105
+ For representing monetary data in ruby, we recomend using the [BigDecimal] (http://ruby-doc.org/stdlib-2.1.1/libdoc/bigdecimal/rdoc/BigDecimal.html) library. If you access data by calling response items as though they were methods on the response itself. If you access data this way, any numerical data will be converted to BigDecimal format.
106
+
107
+ ```ruby
108
+ rest_api.orders(before: Time.now - 60*60) do |resp|
109
+ resp.each do |order|
110
+ p sprintf "#{order.side} ฿ %.8f for $ %.2f", order.size, order.price
111
+ end
112
+ end
113
+ ```
114
+
115
+ ### Errors
116
+
117
+ The gem will throw an error if it detects an exception. The possible errors are:
118
+
119
+ |Error|Description
120
+ |---|---
121
+ |APIError|Parent class for all errors.
122
+ |BadRequestError|Server returned status 400.
123
+ |NotAuthorizedError|Server returned status 401.
124
+ |ForbiddenError|Server returned status 403.
125
+ |NotFoundError|Server returned status 404.
126
+ |RateLimitError|Server returned status 429.
127
+ |InternalServerError|Server returned status 500.
128
+
129
+ ### Metadata
130
+
131
+ You may need more fine-grained access to API response than just the body. We additionally provide access to the response headers, status, and the raw response as represented by the underlying library.
132
+
133
+ ```ruby
134
+ rest_api.last_trade do |resp|
135
+ p "Status: #{resp.response_status}"
136
+ p "Headers: #{resp.response_headers}"
137
+ p "Response: #{resp.raw}"
138
+ end
139
+ ```
140
+
141
+ ## Endpoints
142
+
143
+ ### [Market Data] (https://docs.exchange.coinbase.com/#market-data)
144
+
145
+ Coinbase supports trading in multiple currencies. When interacting with market data, you can get information about a product other than your default by setting the product_id parameter.
146
+
147
+ ```ruby
148
+ rest_api.last_trade(product_id: 'BTC-GBP') do |resp|
149
+ p "The spot rate is £ %.2f" resp.price
150
+ end
151
+ ```
152
+
153
+ **currencies**
154
+
155
+ Fetches a list of currencies we support.
156
+
157
+ ```ruby
158
+ rest_api.currencies do |resp|
159
+ resp.each do |currency|
160
+ p "The symbol for #{currency.name} is #{currency.id}"
161
+ end
162
+ end
163
+ ```
164
+
165
+ **products**
166
+
167
+ Fetches a list of products we offer.
168
+
169
+ ```ruby
170
+ rest_api.products do |resp|
171
+ resp.each do |product|
172
+ p "The most #{product.base_currency} you can buy with #{product.quote_currency} is %f" % product.base_max_size
173
+ end
174
+ end
175
+ ```
176
+
177
+ **orderbook**
178
+
179
+ Downloads a list of all open orders on our exchange.
180
+
181
+ ```ruby
182
+ rest_api.orderbook do |resp|
183
+ p resp
184
+ end
185
+ ```
186
+
187
+ If you wish to download a level 2 or level 3 orderbook, pass a level parameter to the method.
188
+
189
+ ```ruby
190
+ rest_api.orderbook(level: 3) do |resp|
191
+ p "There are #{resp.bids.count} open bids on the orderbook"
192
+ p "There are #{resp.asks.count} open asks on the orderbook"
193
+ end
194
+ ```
195
+
196
+ **last_trade**
197
+
198
+ Downloads information about the last trade, which is exposed through the /ticker endpoint.
199
+
200
+ ```ruby
201
+ rest_api.last_trade do |resp|
202
+ p "The spot rate is $ %.2f" resp.price
203
+ end
204
+ ```
205
+
206
+ **trade_history**
207
+
208
+ Downloads recent trades. Please be aware that if you don't explicitly pass a before parameter this will recursively download every trade that's ever been placed.
209
+
210
+ ```ruby
211
+ rest_api.trade_history(before: Time.now - 10*60) do |resp|
212
+ p "#{resp.count} trades have occured in the past 10 minutes."
213
+ end
214
+ ```
215
+
216
+ **price_history**
217
+
218
+ Downloads price history. We recommend setting a start parameter. You may also find the granularity parameter useful.
219
+
220
+ ```ruby
221
+ rest_api.price_history(start: Time.now - 60*60, granularity: 60) do |resp|
222
+ p "In the past hour, the maximum price movement was $ %.2f" % resp.map { |candle| candle.high - candle.low }.max
223
+ end
224
+ ```
225
+
226
+ **daily_stats**
227
+
228
+ Downloads price information over the past 24 hours.
229
+
230
+ ```ruby
231
+ rest_api.daily_stats do |resp|
232
+ p "The highest price in in the past 24 hours was %.2f" % resp.high
233
+ p "The lowest price in in the past 24 hours was %.2f" % resp.low
234
+ end
235
+ ```
236
+
237
+ ### [Accounts] (https://docs.exchange.coinbase.com/#accounts)
238
+
239
+ **accounts**
240
+
241
+ Downloads information about your accounts.
242
+
243
+ ```ruby
244
+ rest_api.accounts do |resp|
245
+ resp.each do |account|
246
+ p "#{account.id}: %.2f #{account.currency} available for trading" % account.available
247
+ end
248
+ end
249
+ ```
250
+
251
+ **account**
252
+
253
+ Downloads information about a single account. You must pass the account id as the first parameter.
254
+
255
+ ```ruby
256
+ rest_api.account(account_id) do |account|
257
+ p "Account balance is %.2f #{account.currency}" % account.balance
258
+ end
259
+ ```
260
+
261
+ **account_history**
262
+
263
+ Downloads a ledger of transfers, matches, and fees associated with an account. You must pass the account id as the first paramter.
264
+
265
+ ```ruby
266
+ rest_api.account_history(account_id) do |resp|
267
+ p resp
268
+ end
269
+ ```
270
+
271
+ **account_holds**
272
+
273
+ Holds are placed on an account for open orders. This will download a list of all account holds.
274
+
275
+ ```ruby
276
+ rest_api.account_holds(account_id) do |resp|
277
+ p resp
278
+ end
279
+ ```
280
+
281
+ ### [Orders] (https://docs.exchange.coinbase.com/#orders)
282
+
283
+ **bid**
284
+
285
+ Places a buy order. Required parameters are amount and price.
286
+
287
+ ```ruby
288
+ rest_api.bid(0.25, 250) do |resp|
289
+ p "Order ID is #{resp.id}"
290
+ end
291
+ ```
292
+
293
+ **buy**
294
+
295
+ This is an alias for bid.
296
+
297
+ ```ruby
298
+ rest_api.buy(0.25, 250) do |resp|
299
+ p "Order ID is #{resp.id}"
300
+ end
301
+ ```
302
+
303
+ **ask**
304
+
305
+ Places a sell order. Required parameters are amount and price.
306
+
307
+ ```ruby
308
+ rest_api.ask(0.25, 250) do |resp|
309
+ p "Order ID is #{resp.id}"
310
+ end
311
+ ```
312
+
313
+ **sell**
314
+
315
+ This is an alias for ask.
316
+
317
+ ```ruby
318
+ rest_api.sell(0.25, 250) do |resp|
319
+ p "Order ID is #{resp.id}"
320
+ end
321
+ ```
322
+
323
+ **cancel**
324
+
325
+ Cancels an order. This returns no body, but you can still pass a block to execute on a successful return.
326
+
327
+ ```ruby
328
+ rest_api.cancel(order_id) do
329
+ p "Order canceled successfully"
330
+ end
331
+ ```
332
+
333
+ **orders**
334
+
335
+ Downloads a list of all you're orders. Most likely, you only care about your open orders when using this.
336
+
337
+ ```ruby
338
+ rest_api.orders(status: open) do |resp|
339
+ p "You have #{resp.count} open orders."
340
+ end
341
+ ```
342
+
343
+ **order**
344
+
345
+ Downloads information about a single order.
346
+
347
+ ```ruby
348
+ rest_api.order(order_id) do |resp|
349
+ p "Order status is #{resp.status}"
350
+ end
351
+ ```
352
+
353
+ **fills**
354
+
355
+ Downloads a list of fills.
356
+
357
+ ```ruby
358
+ rest_api.fills do |resp|
359
+ p resp
360
+ end
361
+ ```
362
+
363
+ ### [Transfers] (https://docs.exchange.coinbase.com/#transfer-funds)
364
+
365
+ **deposit**
366
+
367
+ Deposit money from a Coinbase wallet.
368
+
369
+ ```ruby
370
+ rest_api.deposit(wallet_id, 10) do |resp|
371
+ p "Deposited 10 BTC"
372
+ end
373
+ ```
374
+
375
+ **withdraw**
376
+
377
+ Withdraw money for your Coinbase wallet.
378
+
379
+ ```ruby
380
+ rest_api.withdraw(wallet_id, 10) do |resp|
381
+ p "Withdrew 10 BTC"
382
+ end
383
+ ```
384
+
385
+ ### Other
386
+
387
+ **server_time**
388
+
389
+ Download the server time.
390
+
391
+ ```ruby
392
+ rest_api.server_time do |resp|
393
+ p "The time on the server is #{resp}"
394
+ end
395
+ ```
396
+
397
+ ## Websocket Client
398
+
399
+ We recommend reading the official websocket documentation before proceeding.
400
+
401
+ * https://docs.exchange.coinbase.com/#websocket-feed
402
+
403
+ We provide a websocket interface in the gem for convenience. This is typically used to build a real-time orderbook, although it can also be used for simpler purposes such as tracking the market rate, or tracking when your orders fill. Like the asynchronous client, this depends Eventmachine for asycnhronous processing.
404
+
405
+ Please consider setting the keepalive flag to true when initializing the websocket. This will cause the websocket to proactively refresh the connection whenever it closes.
406
+
407
+ ```ruby
408
+ websocket = Coinbase::Exchange::Websocket.new(keepalive: true)
409
+ ```
410
+
411
+ Before starting the websocket, you should hook into whatever messages you're interested in by passing a block to the corresponding method. The methods you can use for access are open, match, change, done, and error. Additionally, you can use message to run a block on every websocket event.
412
+
413
+ ```ruby
414
+ require 'coinbase/exchange'
415
+ require 'eventmachine'
416
+
417
+ websocket = Coinbase::Exchange::Websocket.new(product_id: 'BTC-GBP',
418
+ keepalive: true)
419
+ websocket.match do |data|
420
+ p "Spot Rate: £ %.2f" % resp.price
421
+ end
422
+
423
+ EM.run do
424
+ websocket.start!
425
+ EM.add_periodic_timer(1) {
426
+ websocket.ping do
427
+ p "Websocket is alive"
428
+ end
429
+ }
430
+ EM.error_handler { |e|
431
+ p "Websocket Error: #{e.message}"
432
+ }
433
+ end
434
+ ```
435
+
436
+ If started outside the reactor loop, the websocket client will use a very basic Eventmachine handler.
437
+
438
+ ```ruby
439
+ require 'coinbase/exchange'
440
+
441
+ websocket = Coinbase::Exchange::Websocket.new(product_id: 'BTC-GBP')
442
+ websocket.on_match do |data|
443
+ p "Spot Rate: £ %.2f" % resp.price
444
+ end
445
+ websocket.start!
446
+ ```