taproot 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7cd789482e4c1053a87ebce20b53faf67eae60f6
4
+ data.tar.gz: dd3158d834b090e7dcf54536c4c103e03958050a
5
+ SHA512:
6
+ metadata.gz: 669edbfb9cd11cdd762b6682f9f5b46bc8686d15a94fd185ddd0f54ac1584b0853c4f0627b57d340cc4c8485c95530f658c6e40613724bd0181f3007e1167bd1
7
+ data.tar.gz: 47fab4bc960ec0e8e1b2b5dd8f67b6f7fea48d5248ac1cc648b32b9f6f0ce0c1f3f0343e84be1ce8b767aa9f1aa2a697cb1476d31c0641e6bc557a718a929134
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,66 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ taproot (0.1.0)
5
+ activesupport (~> 4.1.1)
6
+ awesome_print (~> 1.2.0)
7
+ braintree (~> 2.30.2)
8
+ pry (~> 0.9.12.6)
9
+ sinatra (~> 1.4.5)
10
+ sinatra-contrib (~> 1.4.2)
11
+ term-ansicolor (~> 1.3.0)
12
+
13
+ GEM
14
+ remote: https://rubygems.org/
15
+ specs:
16
+ activesupport (4.1.1)
17
+ i18n (~> 0.6, >= 0.6.9)
18
+ json (~> 1.7, >= 1.7.7)
19
+ minitest (~> 5.1)
20
+ thread_safe (~> 0.1)
21
+ tzinfo (~> 1.1)
22
+ awesome_print (1.2.0)
23
+ backports (3.6.0)
24
+ braintree (2.30.2)
25
+ builder (>= 2.0.0)
26
+ builder (3.2.2)
27
+ coderay (1.1.0)
28
+ i18n (0.6.9)
29
+ json (1.8.1)
30
+ method_source (0.8.2)
31
+ minitest (5.3.4)
32
+ multi_json (1.10.1)
33
+ pry (0.9.12.6)
34
+ coderay (~> 1.0)
35
+ method_source (~> 0.8)
36
+ slop (~> 3.4)
37
+ rack (1.5.2)
38
+ rack-protection (1.5.3)
39
+ rack
40
+ rack-test (0.6.2)
41
+ rack (>= 1.0)
42
+ sinatra (1.4.5)
43
+ rack (~> 1.4)
44
+ rack-protection (~> 1.4)
45
+ tilt (~> 1.3, >= 1.3.4)
46
+ sinatra-contrib (1.4.2)
47
+ backports (>= 2.0)
48
+ multi_json
49
+ rack-protection
50
+ rack-test
51
+ sinatra (~> 1.4.0)
52
+ tilt (~> 1.3)
53
+ slop (3.5.0)
54
+ term-ansicolor (1.3.0)
55
+ tins (~> 1.0)
56
+ thread_safe (0.3.3)
57
+ tilt (1.4.1)
58
+ tins (1.3.0)
59
+ tzinfo (1.1.0)
60
+ thread_safe (~> 0.1)
61
+
62
+ PLATFORMS
63
+ ruby
64
+
65
+ DEPENDENCIES
66
+ taproot!
data/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # Taproot
2
+
3
+ A test server for Braintree client SDK integrations.
4
+
5
+ ## Features
6
+
7
+ * Switch between multiple Braintree accounts
8
+ * Interactive console
data/bin/taproot ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ require "awesome_print"
3
+ require "cli"
4
+
5
+ if ARGV.first.nil?
6
+ ARGV[0] = "index"
7
+ end
8
+
9
+ ARGV[0] = ARGV[0].gsub("/", "_").gsub(":", "_")
10
+
11
+ if TaprootCLI.respond_to?(ARGV.first.to_sym)
12
+ ap TaprootCLI.send(ARGV.first.to_sym)
13
+ end
data/bin/taprootd ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+ require "taproot"
3
+ require "optparse"
4
+ require "rack"
5
+ require "yaml"
6
+ require "pry"
7
+ require "config_manager"
8
+ require "exception_handler"
9
+
10
+ options = {}
11
+ OptionParser.new do |opts|
12
+ opts.banner = "Usage: taproot [options]"
13
+
14
+ opts.on("--merchant-id [id]", "Braintree Merchant ID") do |v|
15
+ options[:merchant_id] = v
16
+ end
17
+
18
+ opts.on("--environment [env]", "Braintree Environment") do |v|
19
+ options[:environment] = v.to_sym
20
+ end
21
+
22
+ opts.on("--public-key [key]", "Braintree Public Key") do |v|
23
+ options[:public_key] = v
24
+ end
25
+
26
+ opts.on("--private-key [key]", "Braintree Private Key") do |v|
27
+ options[:private_key] = v
28
+ end
29
+
30
+ opts.on("-c [config file]", "--config [config file]", "Taproot YAML config") do |v|
31
+ options[:config_file] = v
32
+ end
33
+
34
+ opts.on("-p [port]", "--port [port]", "Port") do |v|
35
+ options[:port] = v
36
+ end
37
+ end.parse!
38
+
39
+ CONFIG_MANAGER = ConfigManager.new
40
+ config_file = options.fetch(:config_file, "taproot.yml")
41
+
42
+ if File.exists?(config_file)
43
+ config_file = File.read(config_file)
44
+ YAML.load(config_file).fetch("BraintreeAccounts", {}).each do |name, braintree_account_args|
45
+ CONFIG_MANAGER.add(name, braintree_account_args)
46
+ end
47
+ end
48
+
49
+ if ([:merchant_id, :environment, :public_key, :private_key] - options.keys).length == 0
50
+ CONFIG_MANAGER.add(
51
+ "commandline",
52
+ :environment => options[:environment],
53
+ :merchant_id => options[:merchant_id],
54
+ :public_key => options[:public_key],
55
+ :private_key => options[:private_key]
56
+ )
57
+ end
58
+
59
+ unless CONFIG_MANAGER.valid?
60
+ puts "Need at least one Braintree account."
61
+ puts "taproot --help"
62
+ exit 1
63
+ end
64
+
65
+ CONFIG_MANAGER.activate_first!
66
+
67
+ Rack::Handler::WEBrick.run(Taproot, {:Port => options.fetch(:port, "3132")}) do |server|
68
+ [:INT, :TERM].each { |sig| trap(sig) { server.stop } }
69
+ end
data/config.ru ADDED
@@ -0,0 +1,3 @@
1
+ require './app'
2
+ run Taproot
3
+
@@ -0,0 +1,6 @@
1
+ BraintreeAccounts:
2
+ example:
3
+ merchant_id: myid
4
+ environment: sandbox
5
+ public_key: mykey
6
+ private_key: myprikey
@@ -0,0 +1,29 @@
1
+ class BraintreeAccount
2
+ attr_reader :environment, :merchant_id, :public_key, :private_key
3
+
4
+ RequiredOptions = [:environment, :merchant_id, :public_key, :private_key]
5
+
6
+ def initialize(options)
7
+ @environment = options[:environment]
8
+ @merchant_id = options[:merchant_id]
9
+ @public_key = options[:public_key]
10
+ @private_key = options[:private_key]
11
+ end
12
+
13
+ def activate!
14
+ Braintree::Configuration.environment = @environment.to_sym
15
+ Braintree::Configuration.merchant_id = @merchant_id
16
+ Braintree::Configuration.public_key = @public_key
17
+ Braintree::Configuration.private_key = @private_key
18
+ Braintree::Configuration.logger = Logger.new("/dev/null")
19
+ end
20
+
21
+ def as_json
22
+ {
23
+ :environment => @environment,
24
+ :merchant_id => @merchant_id,
25
+ :public_key => @public_key,
26
+ :private_key => @private_key
27
+ }
28
+ end
29
+ end
data/lib/cli.rb ADDED
@@ -0,0 +1,29 @@
1
+ require "net/http"
2
+ require "open-uri"
3
+ require "json"
4
+
5
+ module TaprootCLI
6
+ def self.url(path="")
7
+ URI.join("http://localhost:3132", path)
8
+ end
9
+
10
+ def self.index
11
+ JSON.parse(open(url).read)
12
+ end
13
+
14
+ def self.client_token
15
+ JSON.parse(open(url("client_token")).read)
16
+ end
17
+
18
+ def self.config
19
+ JSON.parse(open(url("config")).read)
20
+ end
21
+
22
+ def self.config_current
23
+ JSON.parse(open(url("config/current")).read)
24
+ end
25
+
26
+ def self.config_merchant_account
27
+ JSON.parse(open(url("config/merchant_account")).read)
28
+ end
29
+ end
@@ -0,0 +1,91 @@
1
+ require "active_support/all"
2
+ require "braintree_account"
3
+ require "open-uri"
4
+ require "timeout"
5
+
6
+
7
+ class ConfigManager
8
+ attr_reader :current, :current_account, :current_merchant_account
9
+ attr_accessor :current_merchant_account
10
+
11
+ def initialize
12
+ @configs = {}.with_indifferent_access
13
+ @current = nil
14
+ @current_account = nil
15
+ @current_merchant_account = nil
16
+ end
17
+
18
+ def as_json
19
+ @configs.inject({}) do |json, (name, config)|
20
+ json[name] = config.as_json
21
+ json
22
+ end
23
+ end
24
+
25
+ def has_config?(name)
26
+ @configs.has_key?(name)
27
+ end
28
+
29
+ def add(name, braintree_account_args)
30
+ @configs[name] = BraintreeAccount.new(braintree_account_args.with_indifferent_access)
31
+ end
32
+
33
+ def valid?
34
+ @configs.any?
35
+ end
36
+
37
+ def activate_first!
38
+ raise "No accounts" unless valid?
39
+ name, braintree_account = @configs.first
40
+ activate!(name)
41
+ end
42
+
43
+ def activate!(name)
44
+ @configs.fetch(name).activate!
45
+ @current = name
46
+ @current_account = @configs.fetch(name)
47
+ end
48
+
49
+ def test_environment!(name)
50
+ original_config = current
51
+ activate!(name)
52
+ rescue Exception => e
53
+ @configs.delete(name)
54
+ raise e
55
+ ensure
56
+ activate!(original_config)
57
+ end
58
+
59
+ def validate_environment!
60
+ old = ::OpenSSL::SSL::VERIFY_PEER
61
+ silence_warnings{ ::OpenSSL::SSL.const_set :VERIFY_PEER, OpenSSL::SSL::VERIFY_NONE }
62
+
63
+ puts "--- [#{current}] Getting client token for validation of environment"
64
+ begin
65
+ client_token = JSON.parse(Braintree::ClientToken.generate)
66
+ rescue Errno::ECONNRESET => e
67
+ return "The gateway is down for URL #{Braintree::Configuration.instantiate.base_merchant_url}"
68
+ rescue Braintree::AuthenticationError => e
69
+ return "Unable to authenticate to Braintree while getteing client token. Your keys or merchant ID may be wrong or the gateway is down."
70
+ end
71
+
72
+ if client_token["paypal"].nil? == false
73
+ puts "--- [#{current}] Trying to connect to paypal"
74
+ begin
75
+ Timeout::timeout(5) { open("#{client_token["paypal"]["baseUrl"]}/paypal") }
76
+ rescue OpenURI::HTTPError => e
77
+ if e.message != "401 Unauthorized"
78
+ return "Error opening #{"#{client_token["paypal"]["baseUrl"]}/paypal"}: #{e.message}"
79
+ end
80
+ rescue Errno::ECONNREFUSED => e
81
+ return "Can't connect to paypal base url #{client_token["paypal"]["baseUrl"]}"
82
+ end
83
+ end
84
+
85
+ "Valid"
86
+ rescue Timeout::Error => e
87
+ "Timed out connecting to paypal at #{"#{client_token["paypal"]["baseUrl"]}/paypal"}"
88
+ ensure
89
+ silence_warnings{ ::OpenSSL::SSL.const_set :VERIFY_PEER, old }
90
+ end
91
+ end
@@ -0,0 +1,20 @@
1
+ class ExceptionHandling
2
+ def initialize(app)
3
+ @app = app
4
+ end
5
+
6
+ def call(env)
7
+ begin
8
+ @app.call env
9
+ rescue => ex
10
+ env['rack.errors'].puts ex
11
+ env['rack.errors'].puts ex.backtrace.join("\n")
12
+ env['rack.errors'].flush
13
+
14
+ hash = { :message => ex.to_s }
15
+ hash[:backtrace] = ex.backtrace[0..5]
16
+
17
+ [500, {'Content-Type' => 'application/json'}, [JSON.pretty_generate(hash)]]
18
+ end
19
+ end
20
+ end
data/lib/taproot.rb ADDED
@@ -0,0 +1,204 @@
1
+ require "rubygems"
2
+ require "sinatra"
3
+ require "sinatra/contrib/all"
4
+ require "braintree"
5
+ require "term/ansicolor"
6
+ require "exception_handler"
7
+ require "config_manager"
8
+
9
+ class Taproot < Sinatra::Base
10
+ use ExceptionHandling
11
+ register Sinatra::Decompile
12
+ include Term::ANSIColor
13
+
14
+ get "/" do
15
+ content_type :json
16
+
17
+ routes = {}
18
+ routes["DELETE"] = Taproot.routes["DELETE"].map { |r| Taproot.decompile(r[0], r[1]) }
19
+ routes["GET"] = Taproot.routes["GET"].map { |r| Taproot.decompile(r[0], r[1]) }
20
+ routes["POST"] = Taproot.routes["POST"].map { |r| Taproot.decompile(r[0], r[1]) }
21
+ routes["PUT"] = Taproot.routes["PUT"].map { |r| Taproot.decompile(r[0], r[1]) }
22
+
23
+ JSON.pretty_generate(:message => "Taproot UP", :config => CONFIG_MANAGER.current, :routes => routes)
24
+ end
25
+
26
+ get "/client_token" do
27
+ content_type :json
28
+ begin
29
+ JSON.pretty_generate(JSON.parse(Braintree::ClientToken.generate(params)))
30
+ rescue Exception => e
31
+ status 422
32
+ JSON.pretty_generate(:message => e.message)
33
+ end
34
+ end
35
+
36
+ put "/customers/:customer_id" do
37
+ result = Braintree::Customer.create(
38
+ :id => params[:customer_id]
39
+ )
40
+
41
+ if result.success?
42
+ status 201
43
+ JSON.pretty_generate(:message => "Customer #{params[:customer_id]} created")
44
+ else
45
+ status 422
46
+ JSON.pretty_generate(:message => result.message)
47
+ end
48
+ end
49
+
50
+ post "/nonce/customer" do
51
+ nonce = nonce_from_params
52
+
53
+ content_type :json
54
+ if nonce
55
+ JSON.pretty_generate(sale(nonce, params.fetch(:amount, 10)))
56
+ else
57
+ JSON.pretty_generate(
58
+ :message => "Required params: #{server_config[:nonce_param_names].join(", or ")}"
59
+ )
60
+ end
61
+ end
62
+
63
+ post "/nonce/transaction" do
64
+ nonce = nonce_from_params
65
+
66
+ content_type :json
67
+ if nonce
68
+ JSON.pretty_generate(sale(nonce, params.fetch(:amount, 10)))
69
+ else
70
+ JSON.pretty_generate(
71
+ :message => "Required params: #{server_config[:nonce_param_names].join(", or ")}"
72
+ )
73
+ end
74
+ end
75
+
76
+ get "/config" do
77
+ content_type :json
78
+ JSON.pretty_generate(CONFIG_MANAGER.as_json)
79
+ end
80
+
81
+ get "/config/current" do
82
+ content_type :json
83
+ JSON.pretty_generate(CONFIG_MANAGER.current_account.as_json)
84
+ end
85
+
86
+ post "/config/:name/activate" do
87
+ content_type :json
88
+
89
+ if CONFIG_MANAGER.has_config?(params[:name])
90
+ status 200
91
+ CONFIG_MANAGER.activate!(params[:name])
92
+ JSON.pretty_generate(:message => "#{params[:name]} activated")
93
+ else
94
+ status 404
95
+ JSON.pretty_generate(:message => "#{params[:name]} not found")
96
+ end
97
+ end
98
+
99
+ put "/config/:name" do
100
+ content_type :json
101
+
102
+ if CONFIG_MANAGER.has_config?(params[:name])
103
+ status 422
104
+ JSON.pretty_generate(:message => "#{params[:name]} already exists")
105
+ else
106
+ begin
107
+ CONFIG_MANAGER.add(
108
+ params[:name],
109
+ :environment => params[:environment],
110
+ :merchant_id => params[:merchant_id],
111
+ :public_key => params[:public_key],
112
+ :private_key => params[:private_key]
113
+ )
114
+ CONFIG_MANAGER.test_environment!(params[:name])
115
+
116
+ status 201
117
+ JSON.pretty_generate(:message => "#{params[:name]} created")
118
+ rescue Exception => e
119
+ status 422
120
+ JSON.pretty_generate(:message => e.message)
121
+ end
122
+ end
123
+ end
124
+
125
+ get "/config/merchant_account" do
126
+ content_type :json
127
+ JSON.pretty_generate(:merchant_account => CONFIG_MANAGER.current_merchant_account)
128
+ end
129
+
130
+ put "/config/merchant_account/:merchant_account" do
131
+ content_type :json
132
+ CONFIG_MANAGER.current_merchant_account = params[:merchant_account]
133
+ JSON.pretty_generate(:merchant_account => CONFIG_MANAGER.current_merchant_account)
134
+ end
135
+
136
+ delete "/config/merchant_account" do
137
+ content_type :json
138
+ CONFIG_MANAGER.current_merchant_account = nil
139
+ JSON.pretty_generate(:merchant_account => CONFIG_MANAGER.current_merchant_account)
140
+ end
141
+
142
+ get "/config/validate" do
143
+ JSON.pretty_generate(:message => CONFIG_MANAGER.validate_environment!)
144
+ end
145
+
146
+ after do
147
+ puts "#{bold ">>>"} #{request.env["REQUEST_METHOD"]} #{request.path} #{params.inspect}"
148
+ puts "#{green bold "<<<"} #{_color_status(response.status.to_i)}"
149
+ response.body.first.split("\n").each do |line|
150
+ puts "#{green bold "<<<"} #{line}"
151
+ end
152
+ end
153
+
154
+ def server_config
155
+ {
156
+ :nonce_param_names => ["nonce", "payment_method_nonce", "paymentMethodNonce"]
157
+ }
158
+ end
159
+
160
+ def log(message)
161
+ puts "--- [#{CONFIG_MANAGER.current}] #{message}"
162
+ end
163
+
164
+ def nonce_from_params
165
+ server_config[:nonce_param_names].find do |nonce_param_name|
166
+ if params[nonce_param_name]
167
+ return params[nonce_param_name]
168
+ end
169
+ end
170
+ end
171
+
172
+ def sale(nonce, amount)
173
+ transaction_params = {
174
+ :amount => amount,
175
+ :payment_method_nonce => nonce,
176
+ }
177
+
178
+ if CONFIG_MANAGER.current_merchant_account
179
+ transaction_params[:merchant_account_id] = CONFIG_MANAGER.current_merchant_account
180
+ end
181
+
182
+ log("Creating transaction #{transaction_params.inspect}")
183
+
184
+ result = Braintree::Transaction.sale(transaction_params)
185
+
186
+ if result.success?
187
+ {:message => "created #{result.transaction.id} #{result.transaction.status}"}
188
+ else
189
+ {:message => result.message}
190
+ end
191
+ rescue Exception => e
192
+ {:message => e.message}
193
+ end
194
+
195
+ def _color_status(status)
196
+ if status >= 400
197
+ yellow status.to_s
198
+ elsif status >= 500
199
+ red status.to_s
200
+ else
201
+ green status.to_s
202
+ end
203
+ end
204
+ end
data/taproot.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.authors = ["Ben Mills"]
5
+ gem.email = ["ben@benmills.org"]
6
+ gem.description = %q{Braintree test server}
7
+ gem.summary = %q{Taproot makes it easy to develop Braintree client SDKs without a server}
8
+ gem.homepage = "https://github.com/benmills/taproot"
9
+
10
+ gem.files = `git ls-files`.split($\)
11
+ gem.executables = ["taprootd", "taproot"]
12
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
+ gem.name = "taproot"
14
+ gem.require_paths = ["lib"]
15
+ gem.version = "0.1.0"
16
+
17
+ gem.add_dependency "sinatra", "~> 1.4.5"
18
+ gem.add_dependency "braintree", "~> 2.30.2"
19
+ gem.add_dependency "pry", "~> 0.9.12.6"
20
+ gem.add_dependency "activesupport", "~> 4.1.1"
21
+ gem.add_dependency "term-ansicolor", "~> 1.3.0"
22
+ gem.add_dependency "awesome_print", "~> 1.2.0"
23
+ gem.add_dependency "sinatra-contrib", "~> 1.4.2"
24
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: taproot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Mills
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sinatra
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 1.4.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 1.4.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: braintree
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 2.30.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 2.30.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.12.6
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.12.6
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 4.1.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 4.1.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: term-ansicolor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 1.3.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 1.3.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: awesome_print
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 1.2.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 1.2.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: sinatra-contrib
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 1.4.2
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 1.4.2
111
+ description: Braintree test server
112
+ email:
113
+ - ben@benmills.org
114
+ executables:
115
+ - taprootd
116
+ - taproot
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - .gitignore
121
+ - Gemfile
122
+ - Gemfile.lock
123
+ - README.md
124
+ - bin/taproot
125
+ - bin/taprootd
126
+ - config.ru
127
+ - example_taproot.yml
128
+ - lib/braintree_account.rb
129
+ - lib/cli.rb
130
+ - lib/config_manager.rb
131
+ - lib/exception_handler.rb
132
+ - lib/taproot.rb
133
+ - taproot.gemspec
134
+ homepage: https://github.com/benmills/taproot
135
+ licenses: []
136
+ metadata: {}
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - '>='
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubyforge_project:
153
+ rubygems_version: 2.0.6
154
+ signing_key:
155
+ specification_version: 4
156
+ summary: Taproot makes it easy to develop Braintree client SDKs without a server
157
+ test_files: []