bitpay-client 2.0.1 → 2.2.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.
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