bitpay-client 2.0.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1d735bbff357cf079a5f5ea6c357e3375644cde5
4
- data.tar.gz: 55b7d5cbbe130d8412e74db9798e1a7bad3ac827
3
+ metadata.gz: b4dc42cd2a385367410f051b9a7def43a3ff3021
4
+ data.tar.gz: c6bd1df8c6e5d47deb49afae0ca2caf0c376f6d6
5
5
  SHA512:
6
- metadata.gz: 43df16582f56058a03896e433f62a8c4338dd40c7598192d0811f437e628ebe601e53d28aa54913fae88a5f89f48b3306255df4153825d136f65504d468de85e
7
- data.tar.gz: 4b679cc6bdae90dbb028081457b8990cf2c33ccc75024e43378ad7a687c36bd94fcee09d3ff2f0ea300e3e679db459483edba53c1c3463ea51f48fe2ad2b98c8
6
+ metadata.gz: 6cb61d057cae19d839dc050028c196256c0837e0f64424985aef98df2dd5d3dd6563c3222b5dd7e0310b1931359916c9ce6c178cab0c30f692fdeac72d82ef6b
7
+ data.tar.gz: 0e326cd00defdeeb8bae777cc42c5189155683aac1be108dcf05801b84dc5f4bab47d8554da6103ecb35514ec51f2c6033c0bc6c06a15a8aadcc75dcbe410aaa
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # BitPay Library for Ruby [![](https://secure.travis-ci.org/bitpay/ruby-client.png)](http://travis-ci.org/bitpay/ruby-client)
1
+ # BitPay Library for Ruby [![](https://travis-ci.org/bitpay/ruby-cli.svg)](http://travis-ci.org/bitpay/ruby-cli)
2
2
  Powerful, flexible, lightweight interface to the BitPay Bitcoin Payment Gateway API.
3
3
 
4
4
  ## Installation
data/Rakefile CHANGED
@@ -3,6 +3,8 @@ require 'rspec/core/rake_task'
3
3
  require 'capybara'
4
4
  require 'capybara/poltergeist'
5
5
  require 'mongo'
6
+ require 'cucumber'
7
+ require 'cucumber/rake/task'
6
8
 
7
9
  require_relative 'config/constants.rb'
8
10
  require_relative 'config/capybara.rb'
@@ -11,32 +13,24 @@ RSpec::Core::RakeTask.new(:spec)
11
13
 
12
14
  task :default => :spec
13
15
 
16
+ Cucumber::Rake::Task.new(:features) do |t|
17
+ t.cucumber_opts = "features --format pretty"
18
+ end
19
+
14
20
  desc "Bitpay Tasks"
15
21
  namespace :bitpay do
16
22
 
17
23
  desc "Clear all claim codes from the test server."
18
24
  task :clear_claim_codes do
19
25
  puts "clearing claim codes"
20
- Capybara.visit ROOT_ADDRESS
21
- Capybara.click_link('Login')
22
- Capybara.fill_in 'email', :with => TEST_USER
23
- Capybara.fill_in 'password', :with => TEST_PASS
24
- Capybara.click_button('loginButton')
25
- Capybara.click_link "My Account"
26
- Capybara.click_link "API Tokens", match: :first
27
- while Capybara.page.has_selector?(".token-claimcode") || Capybara.page.has_selector?(".token-requiredsins-key") do
28
- Capybara.page.find(".api-manager-actions-edit", match: :first).click
29
- Capybara.page.find(".api-manager-actions-revoke", match: :first).click
30
- Capybara.click_button("Confirm Revoke")
31
- # this back and forth bit is here because no other reload mechanism worked, and without it the task errors out: either because it can't find the revoke button or it finds multiple elements at each click point
32
- Capybara.page.go_back
33
- Capybara.click_link "API Tokens", match: :first
34
- end
26
+ client = Mongo::MongoClient.new
27
+ db = client['bitpay-dev']
28
+ coll = db['tokenaccesses']
29
+ coll.remove()
35
30
  puts "claim codes cleared"
36
31
  end
37
32
 
38
33
  desc "Clear rate limiters from local mongo host"
39
-
40
34
  task :clear_rate_limiters do
41
35
  puts "clearing rate limiters"
42
36
  client = Mongo::MongoClient.new
@@ -46,7 +40,35 @@ namespace :bitpay do
46
40
  puts "rate limiters cleared"
47
41
  end
48
42
 
43
+ desc "Clear local pem and token file"
44
+ task :clear_local_files do
45
+ puts "clearing local files"
46
+ HOME_DIR = File.join(Dir.home, '.bitpay')
47
+ KEY_FILE = File.join(HOME_DIR, 'bitpay.pem')
48
+ TOKEN_FILE = File.join(HOME_DIR, 'tokens.json')
49
+ File.delete(KEY_FILE) if File.file?(KEY_FILE)
50
+ File.delete(TOKEN_FILE) if File.file?(TOKEN_FILE)
51
+ puts "local files cleared"
52
+ end
53
+
54
+ desc "Clear tokens, rate limiters, and local files."
55
+ task :clear do
56
+ ["bitpay:clear_local_files", "bitpay:clear_rate_limiters", "bitpay:clear_claim_codes"].each{|task| Rake::Task[task].reenable}
57
+ ["bitpay:clear_local_files", "bitpay:clear_rate_limiters", "bitpay:clear_claim_codes"].each{|task| Rake::Task[task].invoke}
58
+ end
59
+
49
60
  desc "Run specs and clear claim codes and rate_limiters."
50
61
  task :spec_clear => ['spec', 'clear_claim_codes', 'clear_rate_limiters']
51
62
 
63
+ desc "Run specs, clear data, run cukes, clear data"
64
+ task :tests_clear do
65
+ Rake::Task["bitpay:clear"].invoke
66
+ Rake::Task["spec"].invoke
67
+ Rake::Task["bitpay:clear"].reenable
68
+ Rake::Task["bitpay:clear"].invoke
69
+ Rake::Task["features"].invoke
70
+ Rake::Task["bitpay:clear"].reenable
71
+ Rake::Task["bitpay:clear"].invoke
72
+ end
73
+
52
74
  end
data/bin/bitpay CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
- require_relative '../lib/bitpay'
3
2
  require_relative '../lib/bitpay/cli'
3
+ require_relative '../lib/bitpay/cli_client'
@@ -17,19 +17,21 @@ Gem::Specification.new do |s|
17
17
  s.bindir = 'bin'
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
 
20
- s.add_dependency 'json'
21
- s.add_dependency 'rack', '>= 0'
22
- s.add_dependency 'ecdsa'
20
+ s.add_dependency 'bitpay-sdk', '~>2.1'
21
+ s.add_dependency 'json', '~> 1.8.1'
22
+ s.add_dependency 'rack', '~> 1.5.2'
23
+ s.add_dependency 'ecdsa', '~> 1.2.0'
23
24
  s.add_dependency 'commander'
24
25
 
25
- s.add_development_dependency 'rake'
26
- s.add_development_dependency 'webmock'
27
- s.add_development_dependency 'pry'
28
- s.add_development_dependency 'pry-byebug'
29
- s.add_development_dependency 'pry-rescue'
30
- s.add_development_dependency 'capybara'
31
- s.add_development_dependency 'poltergeist'
32
- s.add_development_dependency 'airborne'
33
- s.add_development_dependency 'rspec'
34
- s.add_development_dependency 'mongo'
26
+ s.add_development_dependency 'rake', '~> 10.3.2'
27
+ s.add_development_dependency 'webmock', '~> 1.18.0'
28
+ s.add_development_dependency 'pry', '~> 0.10.1'
29
+ s.add_development_dependency 'pry-byebug', '~> 2.0.0'
30
+ s.add_development_dependency 'pry-rescue', '~> 1.4.1'
31
+ s.add_development_dependency 'capybara', '~> 2.4.3'
32
+ s.add_development_dependency 'cucumber', '~> 1.3.17'
33
+ s.add_development_dependency 'poltergeist', '~> 1.5.1'
34
+ s.add_development_dependency 'airborne', '~> 0.0.20'
35
+ s.add_development_dependency 'rspec', '~> 3.1.0'
36
+ s.add_development_dependency 'mongo', '~> 1.11.1'
35
37
  end
data/config/constants.rb CHANGED
@@ -1,3 +1,5 @@
1
+ BITPAY_ROOT = File.expand_path("~") + "./bp/"
2
+ ## test constants
1
3
  ROOT_ADDRESS = ENV['RCROOTADDRESS']
2
4
  TEST_USER = ENV['RCTESTUSER']
3
5
  TEST_PASS = ENV['RCTESTPASSWORD']
@@ -0,0 +1,26 @@
1
+ Feature: creating an invoice
2
+ The user won't get any money
3
+ If they can't
4
+ Create Invoices
5
+
6
+ Background:
7
+ Given the user is authenticated with BitPay
8
+
9
+ Scenario Outline: The request is correct
10
+ When the user creates an invoice for <price> <currency>
11
+ Then they should recieve an invoice in response for <price> <currency>
12
+ Examples:
13
+ | price | currency |
14
+ | "500.23" | "USD" |
15
+ | "300.21" | "EUR" |
16
+
17
+ Scenario Outline: The invoice contains illegal characters
18
+ When the user creates an invoice for <price> <currency>
19
+ Then they will receive a BitPay::ArgumentError matching <message>
20
+ Examples:
21
+ | price | currency | message |
22
+ | "50,023" | "USD" | "Price must be formatted as a float" |
23
+ | "300.21" | "EaUR" | "Currency is invalid." |
24
+ | "" | "USD" | "Price must be formatted as a float" |
25
+ | "Ten" | "USD" | "Price must be formatted as a float" |
26
+ | "100" | "" | "Currency is invalid." |
@@ -0,0 +1,21 @@
1
+ Feature: pairing with bitpay
2
+ In order to access bitpay
3
+ It is required that the library
4
+ Is able to pair successfully
5
+
6
+ Scenario: the client has a correct pairing code
7
+ Given the user pairs with BitPay with a valid pairing code
8
+ Then the user is paired with BitPay
9
+
10
+ Scenario Outline: the client has a bad pairing code
11
+ Given the user fails to pair with a semantically <valid> code <code>
12
+ Then they will receive a <error> matching <message>
13
+ Examples:
14
+ | valid | code | error | message |
15
+ | valid | "a1b2c3d" | BitPay::BitPayError | "500: Unable to create token" |
16
+ | invalid | "a1b2c3d4" | BitPay::ArgumentError | "pairing code is not legal" |
17
+
18
+ Scenario: the client has a bad port configuration to a closed port
19
+ When the fails to pair with BitPay because of an incorrect port
20
+ Then they will receive a BitPay::ConnectionError matching "Connection refused"
21
+
@@ -0,0 +1,7 @@
1
+ Feature: retrieving an invoice
2
+ The user may want to retrieve invoices
3
+ So that they can view them
4
+
5
+ Scenario: The request is correct
6
+ Given that a user knows an invoice id
7
+ Then they can retrieve that invoice
@@ -0,0 +1,26 @@
1
+ When(/^the user (?:tries to |)creates? an invoice (?:for|without) "(.*?)" (?:or |and |)"(.*?)"$/) do |price, currency|
2
+ begin
3
+ @response = @client.create_invoice(price: price, currency: currency)
4
+ rescue => error
5
+ @error = error
6
+ end
7
+ end
8
+
9
+ Then(/^they should recieve an invoice in response for "(.*?)" "(.*?)"$/) do |price, currency|
10
+ raise "#{@response['price']} != #{price} or #{@response['currency']} != #{currency}" unless (price == @response['price'].to_s && currency == @response['currency'])
11
+ end
12
+
13
+ Given(/^there is an invalid token$/) do
14
+ pending # express the regexp above with the code you wish you had
15
+ end
16
+
17
+ Given(/^that a user knows an invoice id$/) do
18
+ client = new_paired_client
19
+ @id = (client.create_invoice(price: 100, currency: "USD" ))['id']
20
+ end
21
+
22
+ Then(/^they can retrieve that invoice$/) do
23
+ invoice = BitPay::Client.new(api_uri: ROOT_ADDRESS, insecure: true).get_public_invoice(id: @id)
24
+ raise "That's the wrong invoice" unless invoice['id'] == @id
25
+ end
26
+
@@ -0,0 +1,51 @@
1
+ @token = nil
2
+ @error = nil
3
+
4
+ When(/^the user pairs with BitPay(?: with a valid pairing code|)$/) do
5
+ claim_code = get_claim_code_from_server
6
+ pem = BitPay::KeyUtils.generate_pem
7
+ @client = BitPay::Client.new(api_uri: ROOT_ADDRESS, pem: pem, insecure: true)
8
+ @token = @client.pair_pos_client(claim_code)
9
+ end
10
+
11
+ When(/^the fails to pair with BitPay because of an incorrect port$/) do
12
+ pem = BitPay::KeyUtils.generate_pem
13
+ address = ROOT_ADDRESS.split(':').slice(0,2).join(':') + ":999"
14
+ client = BitPay::Client.new(api_uri: address, pem: pem, insecure: true)
15
+ begin
16
+ client.pair_pos_client("1ab2c34")
17
+ raise "pairing unexpectedly worked"
18
+ rescue => error
19
+ @error = error
20
+ true
21
+ end
22
+ end
23
+
24
+ Given(/^the user is authenticated with BitPay$/) do
25
+ @client = new_client_from_stored_values
26
+ end
27
+
28
+ Given(/^the user is paired with BitPay$/) do
29
+ raise "Client is not paired" unless @client.verify_token
30
+ end
31
+
32
+ Given(/^the user has a bad pairing_code "(.*?)"$/) do |arg1|
33
+ # This is a no-op, pairing codes are transient and never actually saved
34
+ end
35
+
36
+ Then(/^the user fails to pair with a semantically (?:in|)valid code "(.*?)"$/) do |code|
37
+ pem = BitPay::KeyUtils.generate_pem
38
+ client = BitPay::Client.new(api_uri: ROOT_ADDRESS, pem: pem, insecure: true)
39
+ begin
40
+ client.pair_pos_client(code)
41
+ raise "pairing unexpectedly worked"
42
+ rescue => error
43
+ @error = error
44
+ true
45
+ end
46
+ end
47
+
48
+ Then(/^they will receive an? (.*?) matching "(.*?)"$/) do |error_class, error_message|
49
+ raise "Error: #{@error.class}, message: #{@error.message}" unless Object.const_get(error_class) == @error.class && @error.message.include?(error_message)
50
+ end
51
+
@@ -0,0 +1,73 @@
1
+ require 'capybara/poltergeist'
2
+ require 'pry'
3
+
4
+ require File.join File.dirname(__FILE__), '..', '..', 'lib', 'bitpay.rb'
5
+ require_relative '../../config/constants.rb'
6
+ require_relative '../../config/capybara.rb'
7
+
8
+ #
9
+ ## Test Variables
10
+ #
11
+ #PEM = "-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEICg7E4NN53YkaWuAwpoqjfAofjzKI7Jq1f532dX+0O6QoAcGBSuBBAAK\noUQDQgAEjZcNa6Kdz6GQwXcUD9iJ+t1tJZCx7hpqBuJV2/IrQBfue8jh8H7Q/4vX\nfAArmNMaGotTpjdnymWlMfszzXJhlw==\n-----END EC PRIVATE KEY-----\n"
12
+ #
13
+ #PUB_KEY = '038d970d6ba29dcfa190c177140fd889fadd6d2590b1ee1a6a06e255dbf22b4017'
14
+ #CLIENT_ID = "TeyN4LPrXiG5t2yuSamKqP3ynVk3F52iHrX"
15
+ module BitPay
16
+ # Location for API Credentials
17
+ BITPAY_CREDENTIALS_DIR = File.join(Dir.home, ".bitpay")
18
+ PRIVATE_KEY_FILE = 'bitpay.pem'
19
+ PRIVATE_KEY_PATH = File.join(BITPAY_CREDENTIALS_DIR, PRIVATE_KEY_FILE)
20
+ TOKEN_FILE = 'tokens.json'
21
+ TOKEN_FILE_PATH = File.join(BITPAY_CREDENTIALS_DIR, TOKEN_FILE)
22
+ end
23
+
24
+ def get_claim_code_from_server
25
+ Capybara::visit ROOT_ADDRESS
26
+ if logged_in
27
+ Capybara::visit "#{ROOT_ADDRESS}/home"
28
+ else
29
+ log_in
30
+ end
31
+ Capybara::click_link "My Account"
32
+ Capybara::click_link "API Tokens", match: :first
33
+ Capybara::find(".token-access-new-button").find(".btn").find(".icon-plus").click
34
+ sleep 0.25
35
+ Capybara::find_button("Add Token", match: :first).click
36
+ Capybara::find(".token-claimcode", match: :first).text
37
+ end
38
+
39
+ def log_in
40
+ Capybara::click_link('Login')
41
+ Capybara::fill_in 'email', :with => TEST_USER
42
+ Capybara::fill_in 'password', :with => TEST_PASS
43
+ Capybara::click_button('loginButton')
44
+ end
45
+
46
+ def new_paired_client
47
+ claim_code = get_claim_code_from_server
48
+ pem = BitPay::KeyUtils.generate_pem
49
+ client = BitPay::Client.new(api_uri: ROOT_ADDRESS, pem: pem, insecure: true)
50
+ client.pair_pos_client(claim_code)
51
+ client
52
+ end
53
+
54
+ def new_client_from_stored_values
55
+ if File.file?(BitPay::PRIVATE_KEY_PATH) && File.file?(BitPay::TOKEN_FILE_PATH)
56
+ token = get_token_from_file
57
+ pem = File.read(BitPay::PRIVATE_KEY_PATH)
58
+ BitPay::Client.new(pem: pem, tokens: token, insecure: true, api_uri: ROOT_ADDRESS )
59
+ else
60
+ claim_code = get_claim_code_from_server
61
+ client = BitPay::Client.new(api_uri: ROOT_ADDRESS, insecure: true)
62
+ client.pair_pos_client(claim_code)
63
+ client
64
+ end
65
+ end
66
+
67
+ def get_token_from_file
68
+ token = JSON.parse(File.read(BitPay::TOKEN_FILE_PATH))
69
+ end
70
+
71
+ def logged_in
72
+ Capybara::has_link?('Dashboard')
73
+ end
data/lib/bitpay/cli.rb CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  require 'rubygems'
6
6
  require 'commander/import'
7
+ require_relative '../bitpay'
7
8
 
8
9
  program :name, 'BitPay Ruby Library CLI'
9
10
  program :version, BitPay::VERSION
@@ -0,0 +1,24 @@
1
+ module BitPay
2
+ class Client < BitPay::SDK::Client
3
+ def initialize opts={}
4
+ pem = File.read(PRIVATE_KEY_PATH) if File.exists?(PRIVATE_KEY_PATH)
5
+ pem = BitPay::KeyUtils.generate_pem unless File.exists?(PRIVATE_KEY_PATH)
6
+ pem = opts[:pem] if opts[:pem]
7
+ File.write(PRIVATE_KEY_PATH, pem)
8
+ opts[:pem] = pem
9
+ super opts
10
+ end
11
+
12
+ def pair_pos_client claim_code
13
+ response = super
14
+ token = get_token_from_response response
15
+ File.write(TOKEN_FILE_PATH, token)
16
+ return response
17
+ end
18
+
19
+ private
20
+ def get_token_from_response response
21
+ ({response["data"][0]["facade"] => response["data"][0]["token"]}).to_json
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ # license Copyright 2011-2014 BitPay, Inc., MIT License
2
+ # see http://opensource.org/licenses/MIT
3
+ # or https://github.com/bitpay/php-bitpay-client/blob/master/LICENSE
4
+
5
+ require 'uri'
6
+ require 'net/https'
7
+ require 'json'
8
+ require 'openssl'
9
+ require 'ecdsa'
10
+ require 'securerandom'
11
+ require 'digest/sha2'
12
+ require 'cgi'
13
+
14
+ module BitPay
15
+ class KeyUtils
16
+ class << self
17
+ ## Generates a new private key and writes to local FS
18
+ #
19
+ def retrieve_or_generate_pem
20
+ begin
21
+ pem = get_local_pem_file
22
+ rescue
23
+ pem = generate_pem
24
+ write_pem_file pem
25
+ end
26
+ pem
27
+ end
28
+
29
+ def write_pem_file pem
30
+ FileUtils.mkdir_p(BITPAY_CREDENTIALS_DIR)
31
+ File.open(PRIVATE_KEY_PATH, 'w') { |file| file.write(pem) }
32
+ end
33
+ ## Gets private key from ENV variable or local FS
34
+ #
35
+ def get_local_pem_file
36
+ File.read(PRIVATE_KEY_PATH) || (raise BitPayError, MISSING_KEY)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -3,5 +3,5 @@
3
3
  # or https://github.com/bitpay/php-bitpay-client/blob/master/LICENSE
4
4
 
5
5
  module BitPay
6
- VERSION = '2.0.1'
6
+ VERSION = '2.2.0'
7
7
  end
data/lib/bitpay.rb CHANGED
@@ -4,31 +4,18 @@
4
4
 
5
5
  libdir = File.dirname(__FILE__)
6
6
  $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
7
- require 'bitpay/client'
7
+ require 'bitpay_sdk'
8
+ require 'bitpay/cli_client'
9
+ require 'bitpay/cli_key_utils'
8
10
  require 'bitpay/version'
9
11
 
10
12
  module BitPay
11
13
 
12
- # Location of SSL Certificate Authority File
13
- # As sourced from http://curl.haxx.se/ca/cacert.pem
14
- CA_FILE = File.join File.dirname(__FILE__), 'bitpay','cacert.pem'
15
-
16
- # Location of API
17
- API_URI = 'https://bitpay.com'
18
- TEST_API_URI = 'https://test.bitpay.com'
19
- CLIENT_REGISTRATION_PATH = '/api-access-request'
20
-
21
- # Location for API Credentials
22
- BITPAY_CREDENTIALS_DIR = File.join(Dir.home, ".bitpay")
14
+ BITPAY_CREDENTIALS_DIR = ENV['RCBITPAYROOT'] || File.expand_path("~") + "/.bitpay/"
23
15
  PRIVATE_KEY_FILE = 'bitpay.pem'
24
16
  PRIVATE_KEY_PATH = File.join(BITPAY_CREDENTIALS_DIR, PRIVATE_KEY_FILE)
17
+ TOKEN_FILE = 'tokens.json'
18
+ TOKEN_FILE_PATH = File.join(BITPAY_CREDENTIALS_DIR, TOKEN_FILE)
25
19
 
26
- # User agent reported to API
27
- USER_AGENT = 'ruby-bitpay-client '+VERSION
28
-
29
20
  MISSING_KEY = 'No Private Key specified. Pass priv_key or set ENV variable PRIV_KEY'
30
- MISSING_PEM = 'No pem file specified. Pass pem or set ENV variable BITPAY_PEM'
31
-
32
- class BitPayError < StandardError; end
33
-
34
21
  end
data/spec/client_spec.rb CHANGED
@@ -11,25 +11,15 @@ end
11
11
 
12
12
  describe BitPay::Client do
13
13
  let(:bitpay_client) { BitPay::Client.new({api_uri: BitPay::TEST_API_URI}) }
14
+ let(:claim_code) { "a12bc3d" }
14
15
 
15
16
  before do
16
17
  allow(BitPay::KeyUtils).to receive(:nonce).and_return('1')
17
18
  stub_request(:get, /#{BitPay::TEST_API_URI}\/tokens.*/).to_return(:status => 200, :body => tokens.to_json, :headers => {})
18
19
  end
19
20
 
20
- describe "#initialize" do
21
-
22
- it 'should be able to get pem file from the env' do
23
- stub_const('ENV', {'BITPAY_PEM' => PEM})
24
- expect {bitpay_client}.to_not raise_error
25
- end
26
-
27
- end
28
21
 
29
22
  describe "#send_request" do
30
- before do
31
- stub_const('ENV', {'BITPAY_PEM' => PEM})
32
- end
33
23
 
34
24
  context "GET" do
35
25
  it 'should generate a get request' do
@@ -50,34 +40,70 @@ describe BitPay::Client do
50
40
  end
51
41
 
52
42
  describe "#pair_pos_client" do
53
- it 'throws a BitPayError with the error message if the token setting fails' do
43
+ before do
54
44
  stub_const('ENV', {'BITPAY_PEM' => PEM})
45
+ end
46
+
47
+ it 'throws a BitPayError with the error message if the token setting fails' do
55
48
  stub_request(:any, /#{BitPay::TEST_API_URI}.*/).to_return(status: 500, body: "{\n \"error\": \"Unable to create token\"\n}")
56
- expect { bitpay_client.pair_pos_client(:claim_code) }.to raise_error(BitPay::BitPayError, '500: Unable to create token')
49
+ expect { bitpay_client.pair_pos_client(claim_code) }.to raise_error(BitPay::BitPayError, '500: Unable to create token')
57
50
  end
58
51
 
59
52
  it 'gracefully handles 4xx errors' do
60
- stub_const('ENV', {'BITPAY_PEM' => PEM})
61
53
  stub_request(:any, /#{BitPay::TEST_API_URI}.*/).to_return(status: 403, body: "{\n \"error\": \"this is a 403 error\"\n}")
62
- expect { bitpay_client.pair_pos_client(:claim_code) }.to raise_error(BitPay::BitPayError, '403: this is a 403 error')
54
+ expect { bitpay_client.pair_pos_client(claim_code) }.to raise_error(BitPay::BitPayError, '403: this is a 403 error')
55
+ end
56
+
57
+ it 'short circuits on invalid pairing codes' do
58
+ 100.times do
59
+ claim_code = an_illegal_claim_code
60
+ expect{bitpay_client.pair_pos_client(claim_code)}.to raise_error BitPay::ArgumentError, "pairing code is not legal"
61
+ end
63
62
  end
64
63
  end
65
64
 
66
65
  describe "#create_invoice" do
67
66
  subject { bitpay_client }
68
- before {stub_const('ENV', {'BITPAY_PEM' => PEM})}
69
67
  it { is_expected.to respond_to(:create_invoice) }
70
68
 
71
- it 'should make call to the server to create an invoice' do
72
- stub_request(:post, /#{BitPay::TEST_API_URI}\/invoices.*/).to_return(:body => '{"data": "awesome"}')
73
- bitpay_client.create_invoice(id: "addd", price: 20, currency: "USD")
74
- assert_requested :post, "#{BitPay::TEST_API_URI}/invoices"
69
+ describe "should make the call to the server to create an invoice" do
70
+ it 'allows numeric input for the price' do
71
+ stub_request(:post, /#{BitPay::TEST_API_URI}\/invoices.*/).to_return(:body => '{"data": "awesome"}')
72
+ bitpay_client.create_invoice(price: 20.00, currency: "USD")
73
+ assert_requested :post, "#{BitPay::TEST_API_URI}/invoices"
74
+ end
75
+
76
+ it 'allows string input for the price' do
77
+ stub_request(:post, /#{BitPay::TEST_API_URI}\/invoices.*/).to_return(:body => '{"data": "awesome"}')
78
+ bitpay_client.create_invoice(price: "20.00", currency: "USD")
79
+ assert_requested :post, "#{BitPay::TEST_API_URI}/invoices"
80
+ end
75
81
  end
76
82
 
77
83
  it 'should pass through the API error message from load_tokens' do
78
84
  stub_request(:get, /#{BitPay::TEST_API_URI}\/tokens.*/).to_return(status: 500, body: '{"error": "load_tokens_error"}')
79
- expect { bitpay_client.create_invoice(id: "addd", price: 20, currency: "USD") }.to raise_error(BitPay::BitPayError, '500: load_tokens_error')
85
+ expect { bitpay_client.create_invoice(price: 20, currency: "USD") }.to raise_error(BitPay::BitPayError, '500: load_tokens_error')
86
+ end
87
+
88
+ it 'verifies the validity of the price argument' do
89
+ expect { bitpay_client.create_invoice(price: "3,999", currency: "USD") }.to raise_error(BitPay::ArgumentError, 'Illegal Argument: Price must be formatted as a float')
90
+ end
91
+
92
+ it 'verifies the validity of the currency argument' do
93
+ expect { bitpay_client.create_invoice(price: "3999", currency: "UASD") }.to raise_error(BitPay::ArgumentError, 'Illegal Argument: Currency is invalid.')
80
94
  end
81
95
  end
82
- end
83
96
 
97
+ describe '#set_token' do
98
+ subject { bitpay_client }
99
+ it { is_expected.to respond_to(:set_token) }
100
+ it 'sets a token in the client' do
101
+
102
+ end
103
+ end
104
+
105
+ describe "#verify_token" do
106
+ subject { bitpay_client }
107
+ it { is_expected.to respond_to(:verify_token) }
108
+ end
109
+ end
@@ -14,17 +14,19 @@ describe "pairing a token", javascript: true, type: :feature do
14
14
  click_button("Add Token")
15
15
  find(".token-claimcode", match: :first).text
16
16
  end
17
- let(:pem) { BitPay::KeyUtils.generate_pem }
18
- let(:client) { BitPay::Client.new(api_uri: ROOT_ADDRESS, pem: pem, insecure: true) }
17
+ context "when no pem file exists" do
18
+ before do
19
+ File.delete(BitPay::PRIVATE_KEY_PATH) if File.exists?(BitPay::PRIVATE_KEY_PATH)
20
+ File.delete(BitPay::TOKEN_FILE) if File.exists?(BitPay::TOKEN_FILE)
21
+ `./bin/bitpay pair #{claimCode} --insecure #{ROOT_ADDRESS}`
22
+ end
19
23
 
20
- context "pairing an unpaired client" do
21
- it "should have no tokens before pairing" do
22
- expect(client.instance_variable_get(:@tokens)).to be_empty
24
+ it "should save a pem file when pairing" do
25
+ expect(File.exists?(BitPay::PRIVATE_KEY_PATH)).to eq true
23
26
  end
24
- it "should have a pos token after pairing" do
25
- client.pair_pos_client(claimCode)
26
- expect(client.instance_variable_get(:@tokens)['pos']).not_to be_empty
27
+
28
+ it "should save a token when pairing" do
29
+ expect(JSON.parse(File.read(BitPay::TOKEN_FILE_PATH))["pos"]).to_not be_nil
27
30
  end
28
31
  end
29
-
30
32
  end
@@ -24,7 +24,7 @@ describe "create an invoice", javascript: true, type: :feature do
24
24
  @client ||= set_client.call
25
25
  @invoice_id ||= SecureRandom.uuid
26
26
  @price ||= (100..150).to_a.sample
27
- @invoice = @client.create_invoice(id: @invoice_id, currency: "USD", price: @price)
27
+ @invoice = @client.create_invoice(currency: "USD", price: @price)
28
28
  end
29
29
 
30
30
  it "should create an invoice" do