uphold 1.0.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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rubocop.yml +32 -0
  4. data/.travis.yml +13 -0
  5. data/Gemfile +10 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +335 -0
  8. data/Rakefile +14 -0
  9. data/lib/uphold/api/auth_token.rb +17 -0
  10. data/lib/uphold/api/card.rb +36 -0
  11. data/lib/uphold/api/contact.rb +34 -0
  12. data/lib/uphold/api/endpoints.rb +26 -0
  13. data/lib/uphold/api/private_transaction.rb +58 -0
  14. data/lib/uphold/api/public_transaction.rb +23 -0
  15. data/lib/uphold/api/ticker.rb +23 -0
  16. data/lib/uphold/api/transparency.rb +15 -0
  17. data/lib/uphold/api/user.rb +23 -0
  18. data/lib/uphold/api.rb +22 -0
  19. data/lib/uphold/client.rb +14 -0
  20. data/lib/uphold/entities/asset.rb +9 -0
  21. data/lib/uphold/entities/auth_token.rb +9 -0
  22. data/lib/uphold/entities/base_entity.rb +27 -0
  23. data/lib/uphold/entities/card.rb +15 -0
  24. data/lib/uphold/entities/contact.rb +13 -0
  25. data/lib/uphold/entities/error.rb +8 -0
  26. data/lib/uphold/entities/ledger_entry.rb +10 -0
  27. data/lib/uphold/entities/oauth_error.rb +9 -0
  28. data/lib/uphold/entities/phone.rb +12 -0
  29. data/lib/uphold/entities/ticker.rb +10 -0
  30. data/lib/uphold/entities/transaction.rb +17 -0
  31. data/lib/uphold/entities/user.rb +18 -0
  32. data/lib/uphold/helpers.rb +23 -0
  33. data/lib/uphold/options.rb +39 -0
  34. data/lib/uphold/pagination.rb +9 -0
  35. data/lib/uphold/request.rb +70 -0
  36. data/lib/uphold/request_data.rb +7 -0
  37. data/lib/uphold/version.rb +3 -0
  38. data/lib/uphold.rb +46 -0
  39. data/spec/fixtures/vcr_cassettes/ledger.yml +56 -0
  40. data/spec/fixtures/vcr_cassettes/me/card.yml +61 -0
  41. data/spec/fixtures/vcr_cassettes/me/cards.yml +67 -0
  42. data/spec/fixtures/vcr_cassettes/me/contact.yml +61 -0
  43. data/spec/fixtures/vcr_cassettes/me/contacts.yml +61 -0
  44. data/spec/fixtures/vcr_cassettes/me/created_card.yml +61 -0
  45. data/spec/fixtures/vcr_cassettes/me/created_contact.yml +61 -0
  46. data/spec/fixtures/vcr_cassettes/me/phones.yml +61 -0
  47. data/spec/fixtures/vcr_cassettes/me/transactions/cancel.yml +61 -0
  48. data/spec/fixtures/vcr_cassettes/me/transactions/commit.yml +62 -0
  49. data/spec/fixtures/vcr_cassettes/me/transactions/create.yml +61 -0
  50. data/spec/fixtures/vcr_cassettes/me/transactions/create_waiting_cancel.yml +118 -0
  51. data/spec/fixtures/vcr_cassettes/me/transactions/create_waiting_resend.yml +118 -0
  52. data/spec/fixtures/vcr_cassettes/me/transactions/resend.yml +61 -0
  53. data/spec/fixtures/vcr_cassettes/me.yml +185 -0
  54. data/spec/fixtures/vcr_cassettes/pats.yml +61 -0
  55. data/spec/fixtures/vcr_cassettes/reserve/transaction.yml +60 -0
  56. data/spec/fixtures/vcr_cassettes/reserve/transactions.yml +60 -0
  57. data/spec/fixtures/vcr_cassettes/tickers.yml +60 -0
  58. data/spec/fixtures/vcr_cassettes/transparency.yml +60 -0
  59. data/spec/integration/api/auth_token_spec.rb +20 -0
  60. data/spec/integration/api/card_spec.rb +47 -0
  61. data/spec/integration/api/contact_spec.rb +53 -0
  62. data/spec/integration/api/private_transactions_spec.rb +74 -0
  63. data/spec/integration/api/public_transaction_spec.rb +35 -0
  64. data/spec/integration/api/ticker_spec.rb +21 -0
  65. data/spec/integration/api/transparency_spec.rb +33 -0
  66. data/spec/integration/api/user_spec.rb +32 -0
  67. data/spec/spec_helper.rb +26 -0
  68. data/spec/support/vcr.rb +8 -0
  69. data/spec/support/webmock.rb +11 -0
  70. data/spec/unit/api/auth_spec.rb +21 -0
  71. data/spec/unit/api/card_spec.rb +47 -0
  72. data/spec/unit/api/contact_spec.rb +53 -0
  73. data/spec/unit/api/private_transaction_spec.rb +114 -0
  74. data/spec/unit/api/public_transaction_spec.rb +34 -0
  75. data/spec/unit/api/ticker_spec.rb +34 -0
  76. data/spec/unit/api/transparency_spec.rb +33 -0
  77. data/spec/unit/api/user_spec.rb +33 -0
  78. data/spec/unit/client_spec.rb +33 -0
  79. data/spec/unit/entities/base_entity_spec.rb +36 -0
  80. data/spec/unit/helper_spec.rb +37 -0
  81. data/spec/unit/request_spec.rb +94 -0
  82. data/uphold.gemspec +30 -0
  83. metadata +296 -0
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ module Uphold
4
+ module API
5
+ describe PrivateTransaction do
6
+ let(:client) { Client.new }
7
+
8
+ context '#create_transaction' do
9
+ it 'creates a transaction for a specific card' do
10
+ card_id = '1234'
11
+ request_data = RequestData.new(
12
+ Endpoints.with_placeholders(Endpoints::CARD_PRIVATE_TRANSACTIONS, ':card' => card_id),
13
+ Entities::Transaction,
14
+ client.authorization_header,
15
+ card_id: card_id, denomination: { currency: 'USD', amount: 10 }, destination: 'foo@bar.com'
16
+ )
17
+ allow(Request).to receive(:perform_with_object)
18
+
19
+ client.create_transaction(card_id: card_id, currency: 'USD', amount: 10, destination: 'foo@bar.com')
20
+
21
+ expect(Request).to have_received(:perform_with_object).
22
+ with(:post, request_data)
23
+ end
24
+ end
25
+
26
+ context '#commit_transaction' do
27
+ it 'commits a transaction for a specific card' do
28
+ card_id = '1234'
29
+ transaction_id = '4567'
30
+ request_data = RequestData.new(
31
+ Endpoints.with_placeholders(Endpoints::COMMIT_TRANSACTION, ':card' => card_id, ':id' => transaction_id),
32
+ Entities::Transaction,
33
+ client.authorization_header
34
+ )
35
+ allow(Request).to receive(:perform_with_object)
36
+
37
+ client.commit_transaction(card_id: card_id, transaction_id: transaction_id)
38
+
39
+ expect(Request).to have_received(:perform_with_object).
40
+ with(:post, request_data)
41
+ end
42
+ end
43
+
44
+ context '#cancel_transaction' do
45
+ it 'cancels a transaction for a specific card' do
46
+ card_id = '1234'
47
+ transaction_id = '4567'
48
+ request_data = RequestData.new(
49
+ Endpoints.with_placeholders(Endpoints::CANCEL_TRANSACTION, ':card' => card_id, ':id' => transaction_id),
50
+ Entities::Transaction,
51
+ client.authorization_header
52
+ )
53
+ allow(Request).to receive(:perform_with_object)
54
+
55
+ client.cancel_transaction(card_id: card_id, transaction_id: transaction_id)
56
+
57
+ expect(Request).to have_received(:perform_with_object).
58
+ with(:post, request_data)
59
+ end
60
+ end
61
+
62
+ context '#resend_transaction' do
63
+ it 'resends a transaction for a specific card' do
64
+ card_id = '1234'
65
+ transaction_id = '4567'
66
+ request_data = RequestData.new(
67
+ Endpoints.with_placeholders(Endpoints::RESEND_TRANSACTION, ':card' => card_id, ':id' => transaction_id),
68
+ Entities::Transaction,
69
+ client.authorization_header
70
+ )
71
+ allow(Request).to receive(:perform_with_object)
72
+
73
+ client.resend_transaction(card_id: card_id, transaction_id: transaction_id)
74
+
75
+ expect(Request).to have_received(:perform_with_object).
76
+ with(:post, request_data)
77
+ end
78
+ end
79
+
80
+ context '#all_user_transactions' do
81
+ it 'lists all the transactions associated with the current user' do
82
+ request_data = RequestData.new(
83
+ Endpoints::USER_PRIVATE_TRANSACTIONS,
84
+ Entities::Transaction,
85
+ client.authorization_header.merge(client.pagination_header_for_range(0..4))
86
+ )
87
+ allow(Request).to receive(:perform_with_objects)
88
+
89
+ client.all_user_transactions
90
+
91
+ expect(Request).to have_received(:perform_with_objects).
92
+ with(:get, request_data)
93
+ end
94
+ end
95
+
96
+ context '#all_card_transactions' do
97
+ it 'lists all the transactions associated with a specific card' do
98
+ card_id = '1234'
99
+ request_data = RequestData.new(
100
+ Endpoints.with_placeholders(Endpoints::CARD_PRIVATE_TRANSACTIONS, ':card' => card_id),
101
+ Entities::Transaction,
102
+ client.authorization_header.merge(client.pagination_header_for_range(0..4))
103
+ )
104
+ allow(Request).to receive(:perform_with_objects)
105
+
106
+ client.all_card_transactions(card_id: card_id)
107
+
108
+ expect(Request).to have_received(:perform_with_objects).
109
+ with(:get, request_data)
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ module Uphold
4
+ module API
5
+ describe PublicTransaction do
6
+ let(:client) { Uphold::Client.new }
7
+
8
+ context '#all_public_transactions' do
9
+ it 'gets all public transactions' do
10
+ request_data = RequestData.new(Endpoints::PUBLIC_TRANSACTIONS, Entities::Transaction, client.authorization_header.merge(client.pagination_header_for_range(0..4)))
11
+ allow(Request).to receive(:perform_with_objects)
12
+
13
+ client.all_public_transactions
14
+
15
+ expect(Request).to have_received(:perform_with_objects).
16
+ with(:get, request_data)
17
+ end
18
+ end
19
+
20
+ context '#find_public_transaction' do
21
+ it 'gets a public transaction' do
22
+ id = '1234'
23
+ request_data = RequestData.new(Endpoints::PUBLIC_TRANSACTIONS + "/#{id}", Entities::Transaction, client.authorization_header)
24
+ allow(Request).to receive(:perform_with_object)
25
+
26
+ client.find_public_transaction(id: id)
27
+
28
+ expect(Request).to have_received(:perform_with_object).
29
+ with(:get, request_data)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ module Uphold
4
+ module API
5
+ describe Ticker do
6
+ let(:client) { Uphold::Client.new }
7
+
8
+ context '#all_tickers' do
9
+ it 'gets all the tickers' do
10
+ request_data = Uphold::RequestData.new(Endpoints::TICKER, Uphold::Entities::Ticker, client.authorization_header)
11
+ allow(Request).to receive(:perform_with_objects)
12
+
13
+ client.all_tickers
14
+
15
+ expect(Request).to have_received(:perform_with_objects).
16
+ with(:get, request_data)
17
+ end
18
+ end
19
+
20
+ context '#find_ticker' do
21
+ it 'gets a specific ticker' do
22
+ currency = 'USD'
23
+ request_data = Uphold::RequestData.new(Endpoints::TICKER + "/#{currency}", Uphold::Entities::Ticker, client.authorization_header)
24
+ allow(Request).to receive(:perform_with_objects)
25
+
26
+ client.find_ticker(currency: currency)
27
+
28
+ expect(Request).to have_received(:perform_with_objects).
29
+ with(:get, request_data)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ module Uphold
4
+ module API
5
+ describe Transparency do
6
+ let(:client) { Client.new }
7
+
8
+ context '#statistics' do
9
+ it 'gets all the uphold reserve stats' do
10
+ request_data = RequestData.new(Endpoints::STATS, Entities::Asset, client.authorization_header)
11
+ allow(Request).to receive(:perform_with_objects)
12
+
13
+ client.statistics
14
+
15
+ expect(Request).to have_received(:perform_with_objects).
16
+ with(:get, request_data)
17
+ end
18
+ end
19
+
20
+ context '#ledger' do
21
+ it 'gets all the uphold reserve stats' do
22
+ request_data = RequestData.new(Endpoints::LEDGER, Entities::LedgerEntry, client.authorization_header)
23
+ allow(Request).to receive(:perform_with_objects)
24
+
25
+ client.ledger
26
+
27
+ expect(Request).to have_received(:perform_with_objects).
28
+ with(:get, request_data)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ module Uphold
4
+ module API
5
+ describe User do
6
+ let(:client) { Uphold::Client.new }
7
+
8
+ context '#me' do
9
+ it 'gets my personal information' do
10
+ request_data = RequestData.new(Endpoints::USER, Entities::User, client.authorization_header)
11
+ allow(Request).to receive(:perform_with_object)
12
+
13
+ client.me
14
+
15
+ expect(Request).to have_received(:perform_with_object).
16
+ with(:get, request_data)
17
+ end
18
+ end
19
+
20
+ context '#phones' do
21
+ it 'gets my associated phone numbers' do
22
+ request_data = RequestData.new(Endpoints::USER_PHONES, Entities::Phone, client.authorization_header)
23
+ allow(Request).to receive(:perform_with_objects)
24
+
25
+ client.phones
26
+
27
+ expect(Request).to have_received(:perform_with_objects).
28
+ with(:get, request_data)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ module Uphold
4
+ describe Client do
5
+ it 'takes a token on initialization' do
6
+ token = 'x'
7
+
8
+ client = Client.new(token: token)
9
+
10
+ expect(client.bearer_token).to eq token
11
+ end
12
+
13
+ it 'gets the token from the ENV if none is provided' do
14
+ token = 'x'
15
+
16
+ with_modified_env UPHOLD_AUTH_TOKEN: token do
17
+ client = Client.new
18
+
19
+ expect(client.bearer_token).to eq token
20
+ end
21
+ end
22
+
23
+ it 'uses the production api by default' do
24
+ Uphold.sandbox = false
25
+ expect(Uphold.api_base).to eq Uphold::Options::API_BASE
26
+ end
27
+
28
+ it 'uses the sandbox api when asked to' do
29
+ Uphold.sandbox = true
30
+ expect(Uphold.api_base).to eq Uphold::Options::SANDBOX_API_BASE
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ module Uphold
4
+ module Entities
5
+ describe BaseEntity do
6
+ class MockEntity < BaseEntity
7
+ attribute :a_key
8
+ end
9
+
10
+ context '#initialize' do
11
+ it 'instantiates instance variables from arguments' do
12
+ entity = MockEntity.new(a_key: 'value')
13
+
14
+ expect(entity.a_key).to eq 'value'
15
+ end
16
+
17
+ it 'converts camelCase to snake_case' do
18
+ entity = MockEntity.new(a_key: 'value')
19
+
20
+ expect(entity.a_key).to eq 'value'
21
+ end
22
+ end
23
+
24
+ context '.from_collection' do
25
+ it 'instantiates each of the entities passed in' do
26
+ entity = double('Entity')
27
+ allow(MockEntity).to receive(:new)
28
+
29
+ MockEntity.from_collection([entity], '0-1/10')
30
+
31
+ expect(MockEntity).to have_received(:new).with(entity)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ module Uphold
4
+ describe Helpers do
5
+ context '.undercored_key' do
6
+ it 'underscores a key correctly' do
7
+ underscored_key = Helpers.underscored_key(:firstName)
8
+
9
+ expect(underscored_key).to eq :first_name
10
+ end
11
+ end
12
+
13
+ context '.camelized_key' do
14
+ it 'camelizes a key correctly' do
15
+ camelized_key = Helpers.camelized_key(:first_name)
16
+
17
+ expect(camelized_key).to eq :firstName
18
+ end
19
+ end
20
+
21
+ context '.underscored_hash' do
22
+ it 'underscores a hash correctly' do
23
+ underscored_hash = Helpers.underscored_hash(firstName: 'name', email: 'email')
24
+
25
+ expect(underscored_hash.keys).to match %i(first_name email)
26
+ end
27
+ end
28
+
29
+ context '.camelized_hash' do
30
+ it 'camelizes a hash correctly' do
31
+ camelized_hash = Helpers.camelized_hash(first_name: 'name', email: 'email')
32
+
33
+ expect(camelized_hash.keys).to match %i(firstName email)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ module Uphold
4
+ shared_examples 'perform request method' do |method_name|
5
+ let(:object_class) { double('ObjectClass', new: nil, from_collection: nil) }
6
+ let(:response) { double('Response', code: 200, parsed_response: '', headers: {}) }
7
+ let(:request) { spy('request', get: response, post: response) }
8
+ let(:client) { Client.new }
9
+
10
+ context ".#{method_name}" do
11
+ it 'makes the correct call for a GET' do
12
+ allow(Request).to receive(:new).and_return(request)
13
+
14
+ Request.public_send(method_name, :get, request_data)
15
+
16
+ expect(request).to have_received(:get)
17
+ end
18
+
19
+ it 'makes the correct call for a POST' do
20
+ allow(Request).to receive(:new).and_return(request)
21
+
22
+ Request.public_send(method_name, :post, request_data)
23
+
24
+ expect(request).to have_received(:post)
25
+ end
26
+
27
+ it 'makes the actual GET call' do
28
+ url = '/some-url'
29
+ WebMockHelpers.uphold_stub_request(:get, url)
30
+ allow(Request).to receive(:get).and_call_original
31
+
32
+ Request.public_send(method_name, :get, request_data(url, client))
33
+
34
+ expect(Request).to have_received(:get).with(url, headers: client.authorization_header)
35
+ end
36
+
37
+ it 'makes the actual POST call' do
38
+ url = '/some-url'
39
+ data = { key: 'value' }
40
+ WebMockHelpers.uphold_stub_request(:post, url)
41
+ allow(Request).to receive(:post).and_call_original
42
+
43
+ Request.public_send(method_name, :post, request_data(url, client, data))
44
+
45
+ expect(Request).to have_received(:post).with(url, body: data, headers: client.authorization_header)
46
+ end
47
+
48
+ it 'makes a call with basic auth' do
49
+ url = '/some-url'
50
+ headers = { header1: 'I am a header' }
51
+ body = { description: 'whatever' }
52
+ request_data = RequestData.new(url, object_class, headers, body)
53
+ WebMockHelpers.uphold_stub_request(:get, url)
54
+ allow(Request).to receive(:get).and_call_original
55
+
56
+ Request.public_send(method_name, :get, request_data)
57
+
58
+ expect(Request).to have_received(:get).with(url, headers: headers, body: body)
59
+ end
60
+
61
+ it 'handles an auth error response' do
62
+ fake_error = { code: '401', error: 'invalid_token', error_description: 'A description' }
63
+ request_data = RequestData.new('/some-url', object_class)
64
+ WebMockHelpers.uphold_stub_request(:get, '/some-url', fake_error, status: 401)
65
+
66
+ result = Request.public_send(method_name, :get, request_data)
67
+
68
+ expect(result).to be_a(Entities::OAuthError)
69
+ expect(result.code).to eq '401'
70
+ end
71
+
72
+ it 'handles an error response' do
73
+ fake_error = { code: '400', errors: {} }
74
+ request_data = RequestData.new('/some-url', object_class)
75
+ WebMockHelpers.uphold_stub_request(:get, '/some-url', fake_error, status: 400)
76
+
77
+ result = Request.public_send(method_name, :get, request_data)
78
+
79
+ expect(result).to be_a(Entities::Error)
80
+ expect(result.code).to eq '400'
81
+ end
82
+ end
83
+
84
+ def request_data(url = anything, client = nil, payload = nil)
85
+ client ||= double('Client', authorization_header: {})
86
+ RequestData.new(url, object_class, client.authorization_header, payload)
87
+ end
88
+ end
89
+
90
+ describe Request do
91
+ include_examples 'perform request method', :perform_with_object
92
+ include_examples 'perform request method', :perform_with_objects
93
+ end
94
+ end
data/uphold.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'uphold/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'uphold'
8
+ spec.version = Uphold::VERSION
9
+ spec.authors = ['Group Buddies']
10
+ spec.email = ['miguel@subvisual.co', 'zamith@subvisual.co']
11
+ spec.summary = %q{A wrapper for the Uphold API}
12
+ spec.homepage = 'https://github.com/subvisual/uphold-ruby'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_dependency 'httparty', '>= 0.13.3'
21
+ spec.add_dependency 'virtus', '>= 1.0.4'
22
+ spec.add_dependency 'dotenv'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.7'
25
+ spec.add_development_dependency 'climate_control'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rubocop', '~> 0.27.1'
28
+ spec.add_development_dependency 'rspec', '~> 3.1.0'
29
+ spec.add_development_dependency 'webmock', '~> 1.20.4'
30
+ end