bullion_vault 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +45 -0
- data/MIT-LICENSE +21 -0
- data/README.mkd +51 -0
- data/Rakefile +8 -0
- data/bullion_vault.gemspec +27 -0
- data/lib/bullion_vault.rb +23 -0
- data/lib/bullion_vault/api.rb +21 -0
- data/lib/bullion_vault/authentication.rb +9 -0
- data/lib/bullion_vault/client.rb +11 -0
- data/lib/bullion_vault/client/login.rb +26 -0
- data/lib/bullion_vault/client/view_balance.rb +11 -0
- data/lib/bullion_vault/client/view_market.rb +11 -0
- data/lib/bullion_vault/configuration.rb +66 -0
- data/lib/bullion_vault/connection.rb +33 -0
- data/lib/bullion_vault/error.rb +29 -0
- data/lib/bullion_vault/request.rb +34 -0
- data/lib/bullion_vault/version.rb +3 -0
- data/lib/faraday/cookie_auth.rb +14 -0
- data/lib/faraday/raise_http_4xx.rb +48 -0
- data/lib/faraday/raise_http_5xx.rb +29 -0
- data/lib/faraday/raise_invalid_cookie.rb +34 -0
- data/spec/bullion_vault/api_spec.rb +67 -0
- data/spec/bullion_vault/client/login_spec.rb +51 -0
- data/spec/bullion_vault/client/view_balance_spec.rb +17 -0
- data/spec/bullion_vault/client/view_market_spec.rb +16 -0
- data/spec/bullion_vault/client_spec.rb +13 -0
- data/spec/bullion_vault_spec.rb +65 -0
- data/spec/faraday/cookie_auth_spec.rb +14 -0
- data/spec/faraday/response_spec.rb +40 -0
- data/spec/fixtures/view_balance.xml +41 -0
- data/spec/fixtures/view_balance.yaml +32 -0
- data/spec/fixtures/view_market.xml +261 -0
- data/spec/fixtures/view_market.yaml +164 -0
- data/spec/spec_helper.rb +37 -0
- metadata +148 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
bullion_vault (0.1.0)
|
5
|
+
faraday_middleware (~> 0.3.2)
|
6
|
+
hashie (~> 1.0.0)
|
7
|
+
multi_xml (~> 0.2.1)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
addressable (2.2.4)
|
13
|
+
crack (0.1.8)
|
14
|
+
diff-lcs (1.1.2)
|
15
|
+
faraday (0.5.7)
|
16
|
+
addressable (~> 2.2.4)
|
17
|
+
multipart-post (~> 1.1.0)
|
18
|
+
rack (< 2, >= 1.1.0)
|
19
|
+
faraday_middleware (0.3.2)
|
20
|
+
faraday (~> 0.5.4)
|
21
|
+
hashie (1.0.0)
|
22
|
+
multi_xml (0.2.1)
|
23
|
+
multipart-post (1.1.0)
|
24
|
+
rack (1.2.2)
|
25
|
+
rake (0.8.7)
|
26
|
+
rspec (2.5.0)
|
27
|
+
rspec-core (~> 2.5.0)
|
28
|
+
rspec-expectations (~> 2.5.0)
|
29
|
+
rspec-mocks (~> 2.5.0)
|
30
|
+
rspec-core (2.5.1)
|
31
|
+
rspec-expectations (2.5.0)
|
32
|
+
diff-lcs (~> 1.1.2)
|
33
|
+
rspec-mocks (2.5.0)
|
34
|
+
webmock (1.6.2)
|
35
|
+
addressable (>= 2.2.2)
|
36
|
+
crack (>= 0.1.7)
|
37
|
+
|
38
|
+
PLATFORMS
|
39
|
+
ruby
|
40
|
+
|
41
|
+
DEPENDENCIES
|
42
|
+
bullion_vault!
|
43
|
+
rake (~> 0.8.7)
|
44
|
+
rspec (~> 2.5.0)
|
45
|
+
webmock (~> 1.6.2)
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2010-2011 William T Nelson, John Nunemaker, Wynn
|
2
|
+
Netherland, Erik Michaels-Ober, Steve Richert
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.mkd
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
BullionVault Ruby Gem
|
2
|
+
====================
|
3
|
+
A Ruby wrapper for the BullionVault XML API
|
4
|
+
|
5
|
+
Installation
|
6
|
+
------------
|
7
|
+
gem install bullion_vault
|
8
|
+
|
9
|
+
Usage Examples
|
10
|
+
--------------
|
11
|
+
require 'rubygems'
|
12
|
+
require 'bullion_vault'
|
13
|
+
require 'pp'
|
14
|
+
|
15
|
+
# Get current market data
|
16
|
+
pp BullionVault.view_market
|
17
|
+
|
18
|
+
# Certain methods require authentication. To get BullionVault credentials,
|
19
|
+
# sign up at https://live.bullionvault.com/secure/registration.do
|
20
|
+
|
21
|
+
BullionVault \
|
22
|
+
.configure {|c| c.user_login, c.user_password = USERNAME, PASSWORD } \
|
23
|
+
.authenticate
|
24
|
+
=> true
|
25
|
+
|
26
|
+
# Check your account
|
27
|
+
pp BullionVault.view_balance
|
28
|
+
|
29
|
+
# You only need a valid session id to be authenticated
|
30
|
+
BullionVault.cookie
|
31
|
+
=> "JSESSIONID=1D034E46B78C47C17005478B6537CABD; Path=/secure; Secure,
|
32
|
+
logintest=\"Thu Mar 31 09:17:26 UTC 2011\"; Version=1; Max-Age=60000;
|
33
|
+
Expires=Fri, 01-Apr-2011 01:57:26 GMT"
|
34
|
+
cookie = 'JSESSIONID=1D034E46B78C47C17005478B6537CABD'
|
35
|
+
BullionVault.cookie = cookie
|
36
|
+
BullionVault.view_balance
|
37
|
+
|
38
|
+
# Use two accounts at once
|
39
|
+
BullionVault.reset
|
40
|
+
c0 = BullionVault::Client.new(:user_login => 'sara_birton')
|
41
|
+
c1 = BullionVault::Client.new(:user_login => 'bonepoppy')
|
42
|
+
|
43
|
+
Documentation
|
44
|
+
-------------
|
45
|
+
* [BullionVault XML API](http://www.bullionvault.com/help/?xml_api.html)
|
46
|
+
* [BullionVault Robots FAQs](http://www.bullionvault.com/help/index.do?content=FAQs/FAQs_bots.html)
|
47
|
+
|
48
|
+
Copyright
|
49
|
+
---------
|
50
|
+
Copyright (c) 2010-2011 William T Nelson, John Nunemaker, Wynn Netherland,
|
51
|
+
Erik Michaels-Ober, Steve Richert. See [MIT-LICENSE](https://github.com/wtn/bullion_vault/blob/master/MIT-LICENSE) for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/bullion_vault/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.add_development_dependency('rspec', '~> 2.5.0')
|
6
|
+
s.add_development_dependency('webmock', '~> 1.6.2')
|
7
|
+
s.add_development_dependency('rake', '~> 0.8.7')
|
8
|
+
s.add_runtime_dependency('faraday_middleware', '~> 0.3.2')
|
9
|
+
s.add_runtime_dependency('multi_xml', '~> 0.2.1')
|
10
|
+
s.add_runtime_dependency('hashie', '~> 1.0.0')
|
11
|
+
|
12
|
+
s.name = 'bullion_vault'
|
13
|
+
s.version = BullionVault::VERSION.dup
|
14
|
+
s.summary = %q{A Ruby wrapper for the BullionVault XML API}
|
15
|
+
s.description = %q{A Ruby wrapper for the BullionVault XML API}
|
16
|
+
s.homepage = 'https://github.com/wtn/bullion_vault'
|
17
|
+
s.authors = ['William T Nelson']
|
18
|
+
s.email = ['wtn@notational.net']
|
19
|
+
s.post_install_message = nil
|
20
|
+
s.rubyforge_project = nil
|
21
|
+
s.platform = Gem::Platform::RUBY
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = ['lib']
|
25
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if s.respond_to?(:required_rubygems_version=)
|
26
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path('../bullion_vault/error', __FILE__)
|
2
|
+
require File.expand_path('../bullion_vault/configuration', __FILE__)
|
3
|
+
require File.expand_path('../bullion_vault/api', __FILE__)
|
4
|
+
require File.expand_path('../bullion_vault/client', __FILE__)
|
5
|
+
require File.expand_path('../bullion_vault/connection', __FILE__)
|
6
|
+
require File.expand_path('../bullion_vault/request', __FILE__)
|
7
|
+
|
8
|
+
module BullionVault
|
9
|
+
extend Configuration
|
10
|
+
|
11
|
+
def self.client(options={})
|
12
|
+
BullionVault::Client.new(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.method_missing(method, *args, &block)
|
16
|
+
return super if ! client.respond_to?(method)
|
17
|
+
client.public_send(method, *args, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.respond_to?(method)
|
21
|
+
return client.respond_to?(method) || super
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path('../connection', __FILE__)
|
2
|
+
require File.expand_path('../request', __FILE__)
|
3
|
+
require File.expand_path('../authentication', __FILE__)
|
4
|
+
|
5
|
+
module BullionVault
|
6
|
+
class API
|
7
|
+
attr_accessor *Configuration::VALID_OPTIONS_KEYS
|
8
|
+
|
9
|
+
# Creates a new API
|
10
|
+
def initialize(options={})
|
11
|
+
options = BullionVault.options.merge(options)
|
12
|
+
Configuration::VALID_OPTIONS_KEYS.each do |key|
|
13
|
+
public_send("#{key}=", options[key])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
include Connection
|
18
|
+
include Request
|
19
|
+
include Authentication
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module BullionVault
|
2
|
+
class Client < API
|
3
|
+
Dir[File.expand_path('../client/*.rb', __FILE__)].each {|f| require f }
|
4
|
+
|
5
|
+
alias :api_endpoint :endpoint
|
6
|
+
|
7
|
+
include BullionVault::Client::Login
|
8
|
+
include BullionVault::Client::ViewMarket
|
9
|
+
include BullionVault::Client::ViewBalance
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module BullionVault
|
2
|
+
class Client
|
3
|
+
module Login
|
4
|
+
HTML_LOGIN_PATH = 'secure/login.do'.freeze
|
5
|
+
XML_LOGIN_PATH = 'secure/j_security_check'.freeze
|
6
|
+
|
7
|
+
def authenticate(raw=false)
|
8
|
+
reset_cookie
|
9
|
+
login(raw)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def login(raw=false)
|
15
|
+
resp = post(XML_LOGIN_PATH, login_credentials, true)
|
16
|
+
raw and return resp
|
17
|
+
resp.status == 302 and resp.headers['location'] == 'https://live.bullionvault.com/secure/main_frame.do'
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset_cookie
|
21
|
+
self.cookie = nil
|
22
|
+
self.cookie = get(HTML_LOGIN_PATH, {}, true).headers['set-cookie']
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require File.expand_path('../version', __FILE__)
|
3
|
+
|
4
|
+
module BullionVault
|
5
|
+
module Configuration
|
6
|
+
VALID_OPTIONS_KEYS = [
|
7
|
+
:adapter,
|
8
|
+
:user_login,
|
9
|
+
:user_password,
|
10
|
+
:endpoint,
|
11
|
+
:format,
|
12
|
+
:proxy,
|
13
|
+
:cookie,
|
14
|
+
:user_agent
|
15
|
+
].freeze
|
16
|
+
|
17
|
+
VALID_FORMATS = [:xml].freeze
|
18
|
+
|
19
|
+
# The default faraday adapter is Net::HTTP.
|
20
|
+
DEFAULT_ADAPTER = Faraday.default_adapter
|
21
|
+
|
22
|
+
DEFAULT_USER_LOGIN = nil
|
23
|
+
DEFAULT_USER_PASSWORD = nil
|
24
|
+
DEFAULT_ENDPOINT = 'https://live.bullionvault.com/'.freeze
|
25
|
+
DEFAULT_FORMAT = 'xml'.freeze
|
26
|
+
DEFAULT_PROXY = nil
|
27
|
+
DEFAULT_COOKIE = nil
|
28
|
+
DEFAULT_USER_AGENT = "BullionVault Ruby Gem #{BullionVault::VERSION}".freeze
|
29
|
+
|
30
|
+
attr_accessor *VALID_OPTIONS_KEYS
|
31
|
+
|
32
|
+
# When this module is extended, set all configuration options to their default values
|
33
|
+
def self.extended(base)
|
34
|
+
base.reset
|
35
|
+
end
|
36
|
+
|
37
|
+
# Convenience method to allow configuration options to be set in a block
|
38
|
+
def configure
|
39
|
+
yield self
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
# Create a hash of options and their values
|
44
|
+
def options
|
45
|
+
Hash[VALID_OPTIONS_KEYS.map {|key| [key, public_send(key)] }]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Reset all configuration options to defaults
|
49
|
+
def reset
|
50
|
+
self.adapter = DEFAULT_ADAPTER
|
51
|
+
self.user_login = DEFAULT_USER_LOGIN
|
52
|
+
self.user_password = DEFAULT_USER_PASSWORD
|
53
|
+
self.endpoint = DEFAULT_ENDPOINT
|
54
|
+
self.format = DEFAULT_FORMAT
|
55
|
+
self.proxy = DEFAULT_PROXY
|
56
|
+
self.cookie = DEFAULT_COOKIE
|
57
|
+
self.user_agent = DEFAULT_USER_AGENT
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def authenticate
|
62
|
+
client = Client.new
|
63
|
+
client.authenticate ? (BullionVault.cookie = client.cookie and true) : false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'faraday_middleware'
|
2
|
+
Dir[File.expand_path('../../faraday/*.rb', __FILE__)].each {|f| require f}
|
3
|
+
|
4
|
+
module BullionVault
|
5
|
+
module Connection
|
6
|
+
private
|
7
|
+
|
8
|
+
def connection(raw=false)
|
9
|
+
options = {
|
10
|
+
:headers => {'User-Agent' => user_agent},
|
11
|
+
:proxy => proxy,
|
12
|
+
:ssl => {:verify => false},
|
13
|
+
:url => api_endpoint,
|
14
|
+
}
|
15
|
+
|
16
|
+
Faraday::Connection.new(options) do |connection|
|
17
|
+
cookie and connection.use Faraday::Request::CookieAuth, cookie
|
18
|
+
connection.adapter(adapter)
|
19
|
+
connection.use Faraday::Response::RaiseHttp5xx
|
20
|
+
parse_xml?(raw).tap do |parse_xml|
|
21
|
+
connection.use Faraday::Response::ParseXml if parse_xml
|
22
|
+
connection.use Faraday::Response::RaiseHttp4xx
|
23
|
+
cookie and connection.use Faraday::Response::RaiseInvalidCookie
|
24
|
+
connection.use Faraday::Response::Mashify if parse_xml
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_xml?(raw)
|
30
|
+
! raw and format.to_s.downcase == 'xml'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module BullionVault
|
2
|
+
class Error < StandardError; end
|
3
|
+
|
4
|
+
class BullionVault::InvalidCookie < Error; end
|
5
|
+
|
6
|
+
# 400
|
7
|
+
class BadRequest < Error; end
|
8
|
+
|
9
|
+
# 401
|
10
|
+
class Unauthorized < Error; end
|
11
|
+
|
12
|
+
# 403
|
13
|
+
class Forbidden < Error; end
|
14
|
+
|
15
|
+
# 404
|
16
|
+
class NotFound < Error; end
|
17
|
+
|
18
|
+
# 406
|
19
|
+
class NotAcceptable < Error; end
|
20
|
+
|
21
|
+
# 500
|
22
|
+
class InternalServerError < Error; end
|
23
|
+
|
24
|
+
# 502
|
25
|
+
class BadGateway < Error; end
|
26
|
+
|
27
|
+
# 503
|
28
|
+
class ServiceUnavailable < Error; end
|
29
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module BullionVault
|
2
|
+
module Request
|
3
|
+
def get(path, options={}, raw=false)
|
4
|
+
request(:get, path, options, raw)
|
5
|
+
end
|
6
|
+
|
7
|
+
def post(path, options={}, raw=false)
|
8
|
+
request(:post, path, options, raw)
|
9
|
+
end
|
10
|
+
|
11
|
+
def put(path, options={}, raw=false)
|
12
|
+
request(:put, path, options, raw)
|
13
|
+
end
|
14
|
+
|
15
|
+
def delete(path, options={}, raw=false)
|
16
|
+
request(:delete, path, options, raw)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def request(method, path, options, raw=false)
|
22
|
+
response = connection(raw).public_send(method) do |request|
|
23
|
+
case method
|
24
|
+
when :get, :delete
|
25
|
+
request.url(path, options)
|
26
|
+
when :post, :put
|
27
|
+
request.path = path
|
28
|
+
request.body = options unless options.empty?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
raw ? response : response.body
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|