mt_gox 0.7.3

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/.gitignore ADDED
@@ -0,0 +1,46 @@
1
+ !.gitignore
2
+ *.gem
3
+ *.rbc
4
+ *.sw[a-p]
5
+ *.tmproj
6
+ *.tmproject
7
+ *.un~
8
+ *~
9
+ .DS_Store
10
+ .Spotlight-V100
11
+ .Trashes
12
+ ._*
13
+ .bundle
14
+ .config
15
+ .directory
16
+ .elc
17
+ .redcar
18
+ .yardoc
19
+ /.emacs.desktop
20
+ /.emacs.desktop.lock
21
+ Desktop.ini
22
+ Gemfile.lock
23
+ Icon?
24
+ InstalledFiles
25
+ Session.vim
26
+ Thumbs.db
27
+ \#*\#
28
+ _yardoc
29
+ auto-save-list
30
+ coverage
31
+ doc/
32
+ lib/bundler/man
33
+ pkg
34
+ pkg/*
35
+ rdoc
36
+ spec/reports
37
+ test/tmp
38
+ test/version_tmp
39
+ tmp
40
+ tmtags
41
+ tramp
42
+
43
+ ## Idea
44
+ .idea
45
+ .rakeTasks
46
+ *.iml
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --order random
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ --tag authenticated:"Requires Authentication"
2
+ --markup markdown
3
+ -
4
+ LICENSE.md
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.md ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Erik Michaels-Ober
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # Ruby wrapper for the Mt. Gox Trade API.
2
+
3
+
4
+ ## <a name="fork"></a>This Fork
5
+ This is a fork of https://github.com/sferik/mtgox. This fork features a rework of the
6
+ original business domain entities into new Models, with an intent to make these Models
7
+ ActiveModel-compliant in future.
8
+
9
+ ## <a name="installation"></a>Installation
10
+ gem install mt_gox
11
+
12
+ ## <a name="alias"></a>Alias
13
+ After installing the gem, you can get the current price for 1 BTC in USD by
14
+ typing `btc` in your bash shell simply by setting the following alias:
15
+
16
+ alias btc='ruby -r rubygems -r mtgox -e "puts MtGox.ticker.sell"'
17
+
18
+ ## <a name="examples"></a>Usage Examples
19
+ require 'rubygems'
20
+ require 'mtgox'
21
+
22
+ # Fetch the latest price for 1 BTC in USD
23
+ puts MtGox.ticker.sell
24
+
25
+ # Fetch open asks
26
+ puts MtGox.asks
27
+
28
+ # Fetch open bids
29
+ puts MtGox.bids
30
+
31
+ # Fetch the last 48 hours worth of trades (takes a minute)
32
+ puts MtGox.trades
33
+
34
+ # Certain methods require authentication
35
+ MtGox.configure do |config|
36
+ config.key = YOUR_MTGOX_KEY
37
+ config.secret = YOUR_MTGOX_SECRET
38
+ end
39
+
40
+ # Fetch your current balance
41
+ puts MtGox.balance
42
+
43
+ # Place a limit order to buy one bitcoin for $0.011
44
+ MtGox.buy! 1.0, 0.011
45
+
46
+ # Place a limit order to sell one bitcoin for $100
47
+ MtGox.sell! 1.0, 100.0
48
+
49
+ # Cancel order #1234567890
50
+ MtGox.cancel 1234567890
51
+
52
+ # Withdraw 1 BTC from your account
53
+ MtGox.withdraw! 1.0, "1KxSo9bGBfPVFEtWNLpnUK1bfLNNT4q31L"
54
+
55
+ [issues]: https://github.com/arvicco/mtgox/issues
56
+
57
+ ## <a name="copyright"></a>Copyright
58
+ Copyright (c) 2011 Erik Michaels-Ober.
59
+ Copyright (c) 2012 Arvicco (extensions).
60
+
61
+ See [LICENSE][] for details.
62
+
63
+ [license]: https://github.com/sferik/mtgox/blob/master/LICENSE.md
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ begin
2
+ require 'rake'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rake', '~> 0.8.3.1'
6
+ require 'rake'
7
+ end
8
+
9
+ require 'pathname'
10
+
11
+ BASE_PATH = Pathname.new(__FILE__).dirname
12
+ LIB_PATH = BASE_PATH + 'lib'
13
+ PKG_PATH = BASE_PATH + 'pkg'
14
+ DOC_PATH = BASE_PATH + 'rdoc'
15
+
16
+ $LOAD_PATH.unshift LIB_PATH.to_s
17
+ require 'mtgox/version'
18
+
19
+ NAME = 'mt_gox'
20
+ CLASS_NAME = MtGox
21
+
22
+ # Load rakefile tasks
23
+ Dir['tasks/*.rake'].sort.each { |file| load file }
24
+
25
+
26
+ # Project-specific tasks
27
+
28
+ require 'yard'
29
+ namespace :doc do
30
+ YARD::Rake::YardocTask.new do |task|
31
+ task.files = ['LICENSE.md', 'lib/**/*.rb']
32
+ task.options = [
33
+ '--tag', 'authenticated:Requires Authentication',
34
+ '--markup', 'markdown',
35
+ ]
36
+ end
37
+ end
38
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.7.3
@@ -0,0 +1,11 @@
1
+ require 'faraday'
2
+
3
+ module Faraday
4
+ class Response::RaiseMtGoxError < Response::Middleware
5
+ def on_complete(env)
6
+ if 200 == env[:status] && 'MySQL error, please retry later' == env[:body]
7
+ raise MtGox::MysqlError, "MySQL error, please retry later"
8
+ end
9
+ end
10
+ end
11
+ end
data/lib/mtgox/ask.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'mtgox/offer'
2
+
3
+ module MtGox
4
+ class Ask < Offer
5
+
6
+ def initialize(price=nil, amount=nil)
7
+ self.price = price.to_f
8
+ self.amount = amount.to_f
9
+ end
10
+
11
+ def eprice
12
+ price / (1 - MtGox.commission)
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ module MtGox
2
+ class Balance
3
+ attr_accessor :currency, :amount
4
+
5
+ def initialize(currency=nil, amount=nil)
6
+ self.currency = currency.to_s.upcase
7
+ self.amount = amount.to_f
8
+ end
9
+ end
10
+ end
data/lib/mtgox/bid.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'mtgox/offer'
2
+
3
+ module MtGox
4
+ class Bid < Offer
5
+
6
+ def initialize(price=nil, amount=nil)
7
+ self.price = price.to_f
8
+ self.amount = amount.to_f
9
+ end
10
+
11
+ def eprice
12
+ price * (1 - MtGox.commission)
13
+ end
14
+
15
+ end
16
+ end
data/lib/mtgox/buy.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'mtgox/order'
2
+
3
+ module MtGox
4
+ class Buy < Order
5
+ end
6
+ end
@@ -0,0 +1,263 @@
1
+ require 'faraday/error'
2
+ require 'mtgox/ask'
3
+ require 'mtgox/balance'
4
+ require 'mtgox/bid'
5
+ require 'mtgox/buy'
6
+ require 'mtgox/connection'
7
+ require 'mtgox/max_bid'
8
+ require 'mtgox/min_ask'
9
+ require 'mtgox/request'
10
+ require 'mtgox/sell'
11
+ require 'mtgox/ticker'
12
+ require 'mtgox/trade'
13
+
14
+ module MtGox
15
+ class Client
16
+ include MtGox::Connection
17
+ include MtGox::Request
18
+
19
+ ORDER_TYPES = {:sell => 1, :buy => 2}
20
+
21
+ # Fetch a deposit address
22
+ # @authenticated true
23
+ # @return [String]
24
+ # @example
25
+ # MtGox.address
26
+ def address
27
+ post('/api/0/btcAddress.php')['addr']
28
+ end
29
+
30
+
31
+ # Fetch the latest ticker data
32
+ #
33
+ # @authenticated false
34
+ # @return [MtGox::Ticker]
35
+ # @example
36
+ # MtGox.ticker
37
+ 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
46
+ Ticker.instance
47
+ end
48
+
49
+ # Fetch both bids and asks in one call, for network efficiency
50
+ #
51
+ # @authenticated false
52
+ # @return [Hash] with keys :asks and :asks, which contain arrays as described in {MtGox::Client#asks} and {MtGox::Clients#bids}
53
+ # @example
54
+ # MtGox.offers
55
+ def offers
56
+ offers = get('/api/0/data/getDepth.php')
57
+ asks = offers['asks'].sort_by do |ask|
58
+ ask[0].to_f
59
+ end.map! do |ask|
60
+ Ask.new(*ask)
61
+ end
62
+ bids = offers['bids'].sort_by do |bid|
63
+ -bid[0].to_f
64
+ end.map! do |bid|
65
+ Bid.new(*bid)
66
+ end
67
+ {:asks => asks, :bids => bids}
68
+ end
69
+
70
+ # Fetch open asks
71
+ #
72
+ # @authenticated false
73
+ # @return [Array<MtGox::Ask>] an array of open asks, sorted in price ascending order
74
+ # @example
75
+ # MtGox.asks
76
+ def asks
77
+ offers[:asks]
78
+ end
79
+
80
+ # Fetch open bids
81
+ #
82
+ # @authenticated false
83
+ # @return [Array<MtGox::Bid>] an array of open bids, sorted in price descending order
84
+ # @example
85
+ # MtGox.bids
86
+ def bids
87
+ offers[:bids]
88
+ end
89
+
90
+ # Fetch the lowest priced ask
91
+ #
92
+ # @authenticated false
93
+ # @return [MtGox::MinAsk]
94
+ # @example
95
+ # MtGox.min_ask
96
+ def min_ask
97
+ min_ask = asks.first
98
+ MinAsk.instance.price = min_ask.price
99
+ MinAsk.instance.amount = min_ask.amount
100
+ MinAsk.instance
101
+ end
102
+
103
+ # Fetch the highest priced bid
104
+ #
105
+ # @authenticated false
106
+ # @return [MtGox::MinBid]
107
+ # @example
108
+ # MtGox.max_bid
109
+ def max_bid
110
+ max_bid = bids.first
111
+ MaxBid.instance.price = max_bid.price
112
+ MaxBid.instance.amount = max_bid.amount
113
+ MaxBid.instance
114
+ end
115
+
116
+ # Fetch recent trades
117
+ #
118
+ # @authenticated false
119
+ # @return [Array<MtGox::Trade>] an array of trades, sorted in chronological order
120
+ # @example
121
+ # MtGox.trades
122
+ def trades
123
+ get('/api/0/data/getTrades.php').sort_by{|trade| trade['date']}.map do |trade|
124
+ Trade.new(trade)
125
+ end
126
+ end
127
+
128
+ # Fetch your current balance
129
+ #
130
+ # @authenticated true
131
+ # @return [Array<MtGox::Balance>]
132
+ # @example
133
+ # MtGox.balance
134
+ def balance
135
+ parse_balance(post('/api/0/getFunds.php', {}))
136
+ end
137
+
138
+ # Fetch your open orders, both buys and sells, for network efficiency
139
+ #
140
+ # @authenticated true
141
+ # @return [Hash] with keys :buys and :sells, which contain arrays as described in {MtGox::Client#buys} and {MtGox::Clients#sells}
142
+ # @example
143
+ # MtGox.orders
144
+ def orders
145
+ parse_orders(post('/api/0/getOrders.php', {})['orders'])
146
+ end
147
+
148
+ # Fetch your open buys
149
+ #
150
+ # @authenticated true
151
+ # @return [Array<MtGox::Buy>] an array of your open bids, sorted by date
152
+ # @example
153
+ # MtGox.buys
154
+ def buys
155
+ orders[:buys]
156
+ end
157
+
158
+ # Fetch your open sells
159
+ #
160
+ # @authenticated true
161
+ # @return [Array<MtGox::Sell>] an array of your open asks, sorted by date
162
+ # @example
163
+ # MtGox.sells
164
+ def sells
165
+ orders[:sells]
166
+ end
167
+
168
+ # Place a limit order to buy BTC
169
+ #
170
+ # @authenticated true
171
+ # @param amount [Numeric] the number of bitcoins to purchase
172
+ # @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}
174
+ # @example
175
+ # # Buy one bitcoin for $0.011
176
+ # MtGox.buy! 1.0, 0.011
177
+ def buy!(amount, price)
178
+ parse_orders(post('/api/0/buyBTC.php', {:amount => amount, :price => price})['orders'])
179
+ end
180
+
181
+ # Place a limit order to sell BTC
182
+ #
183
+ # @authenticated true
184
+ # @param amount [Numeric] the number of bitcoins to sell
185
+ # @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}
187
+ # @example
188
+ # # Sell one bitcoin for $100
189
+ # MtGox.sell! 1.0, 100.0
190
+ def sell!(amount, price)
191
+ parse_orders(post('/api/0/sellBTC.php', {:amount => amount, :price => price})['orders'])
192
+ end
193
+
194
+ # Cancel an open order
195
+ #
196
+ # @authenticated true
197
+ # @overload cancel(oid)
198
+ # @param oid [String] an order ID
199
+ # @return [Hash] with keys :buys and :sells, which contain arrays as described in {MtGox::Client#buys} and {MtGox::Clients#sells}
200
+ # @example
201
+ # my_order = MtGox.orders.first
202
+ # MtGox.cancel my_order.oid
203
+ # MtGox.cancel 1234567890
204
+ # @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)
206
+ # @return [Hash] with keys :buys and :sells, which contain arrays as described in {MtGox::Client#buys} and {MtGox::Clients#sells}
207
+ # @example
208
+ # my_order = MtGox.orders.first
209
+ # MtGox.cancel my_order
210
+ # MtGox.cancel {'oid' => '1234567890', 'type' => 2}
211
+ def cancel(args)
212
+ 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'])
215
+ 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
224
+ end
225
+ end
226
+
227
+ # Transfer bitcoins from your Mt. Gox account into another account
228
+ #
229
+ # @authenticated true
230
+ # @param amount [Numeric] the number of bitcoins to withdraw
231
+ # @param btca [String] the bitcoin address to send to
232
+ # @return [Array<MtGox::Balance>]
233
+ # @example
234
+ # # Withdraw 1 BTC from your account
235
+ # MtGox.withdraw! 1.0, '1KxSo9bGBfPVFEtWNLpnUK1bfLNNT4q31L'
236
+ def withdraw!(amount, btca)
237
+ parse_balance(post('/api/0/withdraw.php', {:group1 => 'BTC', :amount => amount, :btca => btca}))
238
+ end
239
+
240
+ private
241
+
242
+ def parse_balance(balance)
243
+ balances = []
244
+ balances << Balance.new('BTC', balance['btcs'])
245
+ balances << Balance.new('USD', balance['usds'])
246
+ balances
247
+ end
248
+
249
+ def parse_orders(orders)
250
+ buys = []
251
+ sells = []
252
+ orders.sort_by{|order| order['date']}.each do |order|
253
+ case order['type']
254
+ when ORDER_TYPES[:sell]
255
+ sells << Sell.new(order)
256
+ when ORDER_TYPES[:buy]
257
+ buys << Buy.new(order)
258
+ end
259
+ end
260
+ {:buys => buys, :sells => sells}
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,41 @@
1
+ require 'mtgox/version'
2
+
3
+ module MtGox
4
+ module Configuration
5
+ # An array of valid keys in the options hash when configuring a {MtGox::Client}
6
+ VALID_OPTIONS_KEYS = [
7
+ :commission,
8
+ :key,
9
+ :secret,
10
+ ]
11
+
12
+ DEFAULT_COMMISSION = 0.0065.freeze
13
+
14
+ attr_accessor *VALID_OPTIONS_KEYS
15
+
16
+ # When this module is extended, set all configuration options to their default values
17
+ def self.extended(base)
18
+ base.reset
19
+ end
20
+
21
+ # Convenience method to allow configuration options to be set in a block
22
+ def configure
23
+ yield self
24
+ end
25
+
26
+ # Create a hash of options and their values
27
+ def options
28
+ options = {}
29
+ VALID_OPTIONS_KEYS.each{|k| options[k] = send(k)}
30
+ options
31
+ end
32
+
33
+ # Reset all configuration options to defaults
34
+ def reset
35
+ self.commission = DEFAULT_COMMISSION
36
+ self.key = nil
37
+ self.secret = nil
38
+ self
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,32 @@
1
+ require 'faraday'
2
+ require 'faraday/request/url_encoded'
3
+ require 'faraday/response/raise_error'
4
+ require 'faraday/response/parse_json'
5
+ require 'faraday/response/raise_mtgox_error'
6
+ require 'faraday_middleware'
7
+ require 'mtgox/version'
8
+
9
+ module MtGox
10
+ module Connection
11
+ private
12
+
13
+ def connection
14
+ options = {
15
+ :headers => {
16
+ :accept => 'application/json',
17
+ :user_agent => "mt_gox gem #{MtGox::VERSION}",
18
+ },
19
+ :ssl => {:verify => false},
20
+ :url => 'https://mtgox.com',
21
+ }
22
+
23
+ Faraday.new(options) do |connection|
24
+ connection.use Faraday::Request::UrlEncoded
25
+ connection.use Faraday::Response::RaiseError
26
+ connection.use Faraday::Response::ParseJson
27
+ connection.use Faraday::Response::RaiseMtGoxError
28
+ connection.adapter(Faraday.default_adapter)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ module MtGox
2
+ # Custom error class for rescuing from all MtGox errors
3
+ class Error < StandardError; end
4
+
5
+ class MysqlError < Error; end
6
+ end
7
+
@@ -0,0 +1,10 @@
1
+ require 'mtgox/bid'
2
+ require 'mtgox/price_ticker'
3
+ require 'singleton'
4
+
5
+ module MtGox
6
+ class MaxBid < Bid
7
+ include Singleton
8
+ include PriceTicker
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'mtgox/ask'
2
+ require 'mtgox/price_ticker'
3
+ require 'singleton'
4
+
5
+ module MtGox
6
+ class MinAsk < Ask
7
+ include Singleton
8
+ include PriceTicker
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module MtGox
2
+ class Offer
3
+ attr_accessor :amount, :price
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ require 'mtgox/offer'
2
+
3
+ module MtGox
4
+ class Order < Offer
5
+ attr_accessor :id, :date
6
+
7
+ def initialize(order={})
8
+ self.id = order['oid']
9
+ self.date = Time.at(order['date'].to_i)
10
+ self.amount = order['amount'].to_f
11
+ self.price = order['price'].to_f
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ module MtGox
2
+ module PriceTicker
3
+ attr_reader :previous_price, :price
4
+
5
+ def price=(price)
6
+ @previous_price = @price
7
+ @price = price
8
+ end
9
+
10
+ def up?
11
+ price.to_f > previous_price.to_f
12
+ end
13
+
14
+ def down?
15
+ price.to_f < previous_price.to_f
16
+ end
17
+
18
+ def changed?
19
+ price.to_f != previous_price.to_f
20
+ end
21
+
22
+ def unchanged?
23
+ !changed?
24
+ end
25
+ alias :unch? :unchanged?
26
+ end
27
+ end