mtgox 0.8.2 → 0.9.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.
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -1,11 +1,16 @@
1
1
  # Ruby wrapper for the Mt. Gox Trade API
2
+
2
3
  [![Gem Version](https://badge.fury.io/rb/mtgox.png)][gem]
3
4
  [![Build Status](https://secure.travis-ci.org/sferik/mtgox.png?branch=master)][travis]
4
5
  [![Dependency Status](https://gemnasium.com/sferik/mtgox.png?travis)][gemnasium]
6
+ [![Code Climate](https://codeclimate.com/github/sferik/mtgox.png)][codeclimate]
7
+ [![Coverage Status](https://coveralls.io/repos/sferik/mtgox/badge.png?branch=master)][coveralls]
5
8
 
6
9
  [gem]: https://rubygems.org/gems/mtgox
7
10
  [travis]: http://travis-ci.org/sferik/mtgox
8
11
  [gemnasium]: https://gemnasium.com/sferik/mtgox
12
+ [codeclimate]: https://codeclimate.com/github/sferik/mtgox
13
+ [coveralls]: https://coveralls.io/r/sferik/mtgox
9
14
 
10
15
  Mt. Gox allows you to trade US Dollars (USD) for Bitcoins (BTC) or Bitcoins for
11
16
  US Dollars.
@@ -23,11 +28,13 @@ Then, install the gem with the high security trust policy:
23
28
 
24
29
  gem install mtgox -P HighSecurity
25
30
 
26
- ## Alias
31
+ ## Executable
27
32
  After installing the gem, you can get the current price for 1 BTC in USD by
28
- typing `btc` in your bash shell simply by setting the following alias:
33
+ typing `btc` in your bash shell:
34
+
35
+ $ btc
36
+ 50.00
29
37
 
30
- alias btc='ruby -r rubygems -r mtgox -e "puts MtGox.ticker.sell"'
31
38
 
32
39
  ## Documentation
33
40
  [http://rdoc.info/gems/mtgox][documentation]
data/bin/btc ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mtgox'
4
+
5
+ puts MtGox.ticker.sell
@@ -5,6 +5,10 @@ module Faraday
5
5
  def on_complete(env)
6
6
  if 200 == env[:status] && 'MySQL error, please retry later' == env[:body]
7
7
  raise MtGox::MysqlError, "MySQL error, please retry later"
8
+ elsif 403 == env[:status] && MultiJson.load(env[:body])["result"] == "error"
9
+ raise MtGox::UnauthorizedError, MultiJson.load(env[:body])["error"]
10
+ elsif 404 != env[:status] && MultiJson.load(env[:body])["result"] == "error"
11
+ raise MtGox::Error, MultiJson.load(env[:body])["error"]
8
12
  end
9
13
  end
10
14
  end
@@ -1,11 +1,16 @@
1
1
  require 'mtgox/offer'
2
+ require 'mtgox/value'
2
3
 
3
4
  module MtGox
4
5
  class Ask < Offer
6
+ include MtGox::Value
5
7
 
6
- def initialize(price=nil, amount=nil)
7
- self.price = price.to_f
8
- self.amount = amount.to_f
8
+ def initialize(hash = nil)
9
+ if hash
10
+ self.price = value_currency hash, 'price_int'
11
+ self.amount = value_bitcoin hash, 'amount_int'
12
+ self.timestamp = hash['stamp']
13
+ end
9
14
  end
10
15
 
11
16
  def eprice
@@ -1,11 +1,16 @@
1
1
  require 'mtgox/offer'
2
+ require 'mtgox/value'
2
3
 
3
4
  module MtGox
4
5
  class Bid < Offer
6
+ include MtGox::Value
5
7
 
6
- def initialize(price=nil, amount=nil)
7
- self.price = price.to_f
8
- self.amount = amount.to_f
8
+ def initialize(hash = nil)
9
+ if hash
10
+ self.price = value_currency hash, 'price_int'
11
+ self.amount = value_bitcoin hash, 'amount_int'
12
+ self.timestamp = hash['stamp']
13
+ end
9
14
  end
10
15
 
11
16
  def eprice
@@ -10,13 +10,15 @@ require 'mtgox/request'
10
10
  require 'mtgox/sell'
11
11
  require 'mtgox/ticker'
12
12
  require 'mtgox/trade'
13
+ require 'mtgox/value'
13
14
 
14
15
  module MtGox
15
16
  class Client
16
17
  include MtGox::Connection
17
18
  include MtGox::Request
19
+ include MtGox::Value
18
20
 
19
- ORDER_TYPES = {sell: 1, buy: 2}
21
+ ORDER_TYPES = {sell: "ask", buy: "bid"}
20
22
 
21
23
  # Fetch a deposit address
22
24
  # @authenticated true
@@ -24,7 +26,7 @@ module MtGox
24
26
  # @example
25
27
  # MtGox.address
26
28
  def address
27
- post('/api/0/btcAddress.php')['addr']
29
+ post('/api/1/generic/bitcoin/address')['addr']
28
30
  end
29
31
 
30
32
 
@@ -35,14 +37,15 @@ module MtGox
35
37
  # @example
36
38
  # MtGox.ticker
37
39
  def ticker
38
- ticker = get('/api/0/data/ticker.php')['ticker']
39
- Ticker.instance.buy = ticker['buy'].to_f
40
- Ticker.instance.high = ticker['high'].to_f
41
- Ticker.instance.price = ticker['last'].to_f
42
- Ticker.instance.low = ticker['low'].to_f
43
- Ticker.instance.sell = ticker['sell'].to_f
44
- Ticker.instance.volume = ticker['vol'].to_f
45
- Ticker.instance.vwap = ticker['vwap'].to_f
40
+ ticker = get('/api/1/BTCUSD/ticker')
41
+ Ticker.instance.buy = value_currency ticker['buy']
42
+ Ticker.instance.high = value_currency ticker['high']
43
+ Ticker.instance.price = value_currency ticker['last_all']
44
+ Ticker.instance.low = value_currency ticker['low']
45
+ Ticker.instance.sell = value_currency ticker['sell']
46
+ Ticker.instance.volume = value_bitcoin ticker['vol']
47
+ Ticker.instance.vwap = value_currency ticker['vwap']
48
+ Ticker.instance.avg = value_currency ticker['avg']
46
49
  Ticker.instance
47
50
  end
48
51
 
@@ -53,16 +56,16 @@ module MtGox
53
56
  # @example
54
57
  # MtGox.offers
55
58
  def offers
56
- offers = get('/api/0/data/getDepth.php')
59
+ offers = get('/api/1/BTCUSD/depth/fetch')
57
60
  asks = offers['asks'].sort_by do |ask|
58
- ask[0].to_f
61
+ ask['price_int'].to_i
59
62
  end.map! do |ask|
60
- Ask.new(*ask)
63
+ Ask.new(ask)
61
64
  end
62
65
  bids = offers['bids'].sort_by do |bid|
63
- -bid[0].to_f
66
+ -bid['price_int'].to_i
64
67
  end.map! do |bid|
65
- Bid.new(*bid)
68
+ Bid.new(bid)
66
69
  end
67
70
  {asks: asks, bids: bids}
68
71
  end
@@ -120,7 +123,7 @@ module MtGox
120
123
  # @example
121
124
  # MtGox.trades
122
125
  def trades
123
- get('/api/0/data/getTrades.php').sort_by{|trade| trade['date']}.map do |trade|
126
+ get('/api/1/BTCUSD/trades/fetch').sort_by{|trade| trade['date']}.map do |trade|
124
127
  Trade.new(trade)
125
128
  end
126
129
  end
@@ -132,7 +135,7 @@ module MtGox
132
135
  # @example
133
136
  # MtGox.balance
134
137
  def balance
135
- parse_balance(post('/api/0/getFunds.php', {}))
138
+ parse_balance(post('/api/1/generic/info', {}))
136
139
  end
137
140
 
138
141
  # Fetch your open orders, both buys and sells, for network efficiency
@@ -142,7 +145,7 @@ module MtGox
142
145
  # @example
143
146
  # MtGox.orders
144
147
  def orders
145
- parse_orders(post('/api/0/getOrders.php', {})['orders'])
148
+ parse_orders post('/api/1/generic/orders', {})
146
149
  end
147
150
 
148
151
  # Fetch your open buys
@@ -170,12 +173,12 @@ module MtGox
170
173
  # @authenticated true
171
174
  # @param amount [Numeric] the number of bitcoins to purchase
172
175
  # @param price [Numeric] the bid price in US dollars
173
- # @return [Hash] with keys :buys and :sells, which contain arrays as described in {MtGox::Client#buys} and {MtGox::Clients#sells}
176
+ # @return [String] order ID for the buy, can be inspected using order_result
174
177
  # @example
175
178
  # # Buy one bitcoin for $0.011
176
179
  # MtGox.buy! 1.0, 0.011
177
180
  def buy!(amount, price)
178
- parse_orders(post('/api/0/buyBTC.php', {amount: amount, price: price})['orders'])
181
+ addorder!(:buy, amount, price)
179
182
  end
180
183
 
181
184
  # Place a limit order to sell BTC
@@ -183,12 +186,26 @@ module MtGox
183
186
  # @authenticated true
184
187
  # @param amount [Numeric] the number of bitcoins to sell
185
188
  # @param price [Numeric] the ask price in US dollars
186
- # @return [Hash] with keys :buys and :sells, which contain arrays as described in {MtGox::Client#buys} and {MtGox::Clients#sells}
189
+ # @return [String] order ID for the sell, can be inspected using order_result
187
190
  # @example
188
191
  # # Sell one bitcoin for $100
189
192
  # MtGox.sell! 1.0, 100.0
190
193
  def sell!(amount, price)
191
- parse_orders(post('/api/0/sellBTC.php', {amount: amount, price: price})['orders'])
194
+ addorder!(:sell, amount, price)
195
+ end
196
+
197
+ # Create a new order
198
+ #
199
+ # @authenticated true
200
+ # @param type [String] the type of order to create, either "buy" or "sell"
201
+ # @param amount [Numberic] the number of bitcoins to buy/sell
202
+ # @param price [Numeric] the bid/ask price in USD
203
+ # @return [String] order ID for the order, can be inspected using order_result
204
+ # @example
205
+ # # Sell one bitcoin for $123
206
+ # MtGox.addorder! :sell, 1.0, 123.0
207
+ def addorder!(type, amount, price)
208
+ post('/api/1/BTCUSD/order/add', {type: order_type(type), amount_int: intify(amount,:btc), price_int: intify(price, :usd)})
192
209
  end
193
210
 
194
211
  # Cancel an open order
@@ -202,25 +219,25 @@ module MtGox
202
219
  # MtGox.cancel my_order.oid
203
220
  # MtGox.cancel 1234567890
204
221
  # @overload cancel(order)
205
- # @param order [Hash] a hash-like object, with keys `oid` - the order ID of the transaction to cancel and `type` - the type of order to cancel (`1` for sell or `2` for buy)
222
+ # @param order [Hash] a hash-like object, containing at least a key `oid` - the order ID of the transaction to cancel
206
223
  # @return [Hash] with keys :buys and :sells, which contain arrays as described in {MtGox::Client#buys} and {MtGox::Clients#sells}
207
224
  # @example
208
225
  # my_order = MtGox.orders.first
209
226
  # MtGox.cancel my_order
210
- # MtGox.cancel {'oid' => '1234567890', 'type' => 2}
227
+ # MtGox.cancel {'oid' => '1234567890'}
211
228
  def cancel(args)
212
229
  if args.is_a?(Hash)
213
- order = args.delete_if{|k, v| !['oid', 'type'].include?(k.to_s)}
214
- parse_orders(post('/api/0/cancelOrder.php', order)['orders'])
230
+ args = args['oid']
231
+ end
232
+
233
+ orders = post('/api/1/generic/orders', {})
234
+ order = orders.find{|order| order['oid'] == args.to_s}
235
+ if order
236
+ res = post('/api/1/BTCUSD/order/cancel', {oid: order['oid']})
237
+ orders.delete_if { |o| o['oid'] == res['oid'] }
238
+ parse_orders(orders)
215
239
  else
216
- orders = post('/api/0/getOrders.php', {})['orders']
217
- order = orders.find{|order| order['oid'] == args.to_s}
218
- if order
219
- order = order.delete_if{|k, v| !['oid', 'type'].include?(k.to_s)}
220
- parse_orders(post('/api/0/cancelOrder.php', order)['orders'])
221
- else
222
- raise Faraday::Error::ResourceNotFound, {status: 404, headers: {}, body: 'Order not found.'}
223
- end
240
+ raise Faraday::Error::ResourceNotFound, {status: 404, headers: {}, body: 'Order not found.'}
224
241
  end
225
242
  end
226
243
 
@@ -228,21 +245,28 @@ module MtGox
228
245
  #
229
246
  # @authenticated true
230
247
  # @param amount [Numeric] the number of bitcoins to withdraw
231
- # @param btca [String] the bitcoin address to send to
232
- # @return [Array<MtGox::Balance>]
248
+ # @param address [String] the bitcoin address to send to
249
+ # @return [String] Completed Transaction ID
233
250
  # @example
234
251
  # # Withdraw 1 BTC from your account
235
252
  # MtGox.withdraw! 1.0, '1KxSo9bGBfPVFEtWNLpnUK1bfLNNT4q31L'
236
- def withdraw!(amount, btca)
237
- parse_balance(post('/api/0/withdraw.php', {group1: 'BTC', amount: amount, btca: btca}))
253
+ def withdraw!(amount, address)
254
+ if amount >= 1000
255
+ raise FilthyRichError,
256
+ "#withdraw! take bitcoin amount as parameter (you are trying to withdraw #{amount} BTC"
257
+ else
258
+ post('/api/1/generic/bitcoin/send_simple', {amount_int: intify(amount, :btc), address: address})['trx']
259
+ end
238
260
  end
239
261
 
240
262
  private
241
263
 
242
- def parse_balance(balance)
264
+ def parse_balance(info)
243
265
  balances = []
244
- balances << Balance.new('BTC', balance['btcs'])
245
- balances << Balance.new('USD', balance['usds'])
266
+ info['Wallets'].each do |currency, wallet|
267
+ value = currency == "BTC" ? value_bitcoin(wallet['Balance']) : value_currency(wallet['Balance'])
268
+ balances << Balance.new(currency, value)
269
+ end
246
270
  balances
247
271
  end
248
272
 
@@ -259,5 +283,13 @@ module MtGox
259
283
  end
260
284
  {buys: buys, sells: sells}
261
285
  end
286
+
287
+ def order_type(type)
288
+ unless ["bid", "ask"].include?(type.to_s)
289
+ ORDER_TYPES[type.downcase.to_sym]
290
+ else
291
+ type
292
+ end
293
+ end
262
294
  end
263
295
  end
@@ -15,7 +15,7 @@ module MtGox
15
15
  accept: 'application/json',
16
16
  user_agent: "mtgox gem #{MtGox::Version}",
17
17
  },
18
- url: 'https://mtgox.com',
18
+ url: 'https://data.mtgox.com',
19
19
  }
20
20
 
21
21
  Faraday.new(options) do |connection|
@@ -1,7 +1,8 @@
1
1
  module MtGox
2
2
  # Custom error class for rescuing from all MtGox errors
3
3
  class Error < StandardError; end
4
-
5
4
  class MysqlError < Error; end
5
+ class UnauthorizedError < Error; end
6
+ class FilthyRichError < Error; end
6
7
  end
7
8
 
@@ -1,5 +1,5 @@
1
1
  module MtGox
2
2
  class Offer
3
- attr_accessor :amount, :price
3
+ attr_accessor :amount, :price, :timestamp
4
4
  end
5
5
  end
@@ -7,8 +7,8 @@ module MtGox
7
7
  def initialize(order={})
8
8
  self.id = order['oid']
9
9
  self.date = Time.at(order['date'].to_i)
10
- self.amount = order['amount'].to_f
11
- self.price = order['price'].to_f
10
+ self.amount = order['amount']['value'].to_f
11
+ self.price = order['price']['value'].to_f
12
12
  end
13
13
  end
14
14
  end
@@ -23,7 +23,11 @@ module MtGox
23
23
  request.headers = headers(request.body)
24
24
  end
25
25
  end
26
- response.body
26
+ if response.body['result'] && response.body['result'] == 'success'
27
+ response.body['return']
28
+ else
29
+ response.body
30
+ end
27
31
  end
28
32
 
29
33
  def headers(request)
@@ -5,6 +5,6 @@ module MtGox
5
5
  class Ticker
6
6
  include Singleton
7
7
  include PriceTicker
8
- attr_accessor :buy, :sell, :high, :low, :volume, :vwap
8
+ attr_accessor :buy, :sell, :high, :low, :volume, :vwap, :avg
9
9
  end
10
10
  end
@@ -0,0 +1,53 @@
1
+ # In the "old API", currency- and amount-values (price, volume,...)
2
+ # were given as float. These values are likely being deprecated and
3
+ # replaced by fields of the same name with "_int" as suffix. These are
4
+ # fixed-decimal, so you have to move the decimal point yourself
5
+ # (divide). The exponent differs based on the kind of the value.
6
+
7
+ module MtGox
8
+ module Value
9
+ # We assume here that any other currency than :jpy uses :usd
10
+ INT_MULTIPLIERS = {btc: 100000000, usd: 100000, jpy: 1000}
11
+
12
+ # Takes a hash return by the API and convert some value_int to a
13
+ # currency value using USD conversion rule. You can specify which
14
+ # key to convert
15
+ #
16
+ # @param value [Hash] a hash from the API
17
+ # params key [String] the key from the previous hash to convert, default to 'value_int'
18
+ # @authenticated false
19
+ # @return [Float]
20
+ def value_currency(value, key = 'value_int')
21
+ floatify(value[key].to_i, :usd)
22
+ end
23
+
24
+ # Takes a hash return by the API and convert some value_int to
25
+ # [Float] BitCoin value . You can specify which key to convert
26
+ #
27
+ # @param value [Hash] a hash from the API
28
+ # params key [String] the key from the previous hash to convert, default to 'value_int'
29
+ # @authenticated false
30
+ # @return [Float] a float BTC value
31
+ def value_bitcoin(value, key = 'value_int')
32
+ floatify(value[key], :btc)
33
+ end
34
+
35
+ # Convert a float value to an int using the MtGox conversion rules.
36
+ #
37
+ # param float [Float] to convert
38
+ # param currency [Symbol] currency conversion rule to use amongst [:btc, :usd, :jpy]
39
+ # return an int
40
+ def intify(float, currency)
41
+ (float * INT_MULTIPLIERS[currency]).to_i
42
+ end
43
+
44
+ # Convert an int value to a float using the MtGox conversion rules.
45
+ #
46
+ # param int [Fixnum] to convert
47
+ # param currency [Symbol] currency conversion rule to use amongst [:btc, :usd, :jpy]
48
+ # return a [Float]
49
+ def floatify(int, currency)
50
+ (int.to_f / INT_MULTIPLIERS[currency])
51
+ end
52
+ end
53
+ end
@@ -8,12 +8,12 @@ module MtGox
8
8
 
9
9
  # @return [Integer]
10
10
  def self.minor
11
- 8
11
+ 9
12
12
  end
13
13
 
14
14
  # @return [Integer]
15
15
  def self.patch
16
- 2
16
+ 0
17
17
  end
18
18
 
19
19
  # @return [String, NilClass]