starlingrb 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d93eea4aead2fbfebd8fc5ae0e01f0d49620476f796328387f8086297cddcd8f
4
+ data.tar.gz: 786317b144325616e05276784dbbf1a7690c2b53e784972d7d6b5ebdfebef41b
5
+ SHA512:
6
+ metadata.gz: 01d2dd018610e64f9758205c74da9a8053bd69549c39ee4f52930a96c51a6db8c8e99a7962e914009e602158ca0ce961a61edf0095ad929d7925799d2a4c2cf2
7
+ data.tar.gz: 0dd89eac0ea660bf1a599097123ca73c6eb80b424bc14ffc07224984bbe8e2b749acd1580f2d0a1fa44c7d1657669801f37746333d032c4187afe79b4140c26a
data/.env.example ADDED
@@ -0,0 +1 @@
1
+ STARLING_ACCESS_TOKEN=
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in starling.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+ gem "dotenv"
data/Gemfile.lock ADDED
@@ -0,0 +1,46 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ starlingrb (0.1.0)
5
+ faraday (~> 1.7)
6
+ faraday_middleware (~> 1.1)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ dotenv (2.7.6)
12
+ faraday (1.8.0)
13
+ faraday-em_http (~> 1.0)
14
+ faraday-em_synchrony (~> 1.0)
15
+ faraday-excon (~> 1.1)
16
+ faraday-httpclient (~> 1.0.1)
17
+ faraday-net_http (~> 1.0)
18
+ faraday-net_http_persistent (~> 1.1)
19
+ faraday-patron (~> 1.0)
20
+ faraday-rack (~> 1.0)
21
+ multipart-post (>= 1.2, < 3)
22
+ ruby2_keywords (>= 0.0.4)
23
+ faraday-em_http (1.0.0)
24
+ faraday-em_synchrony (1.0.0)
25
+ faraday-excon (1.1.0)
26
+ faraday-httpclient (1.0.1)
27
+ faraday-net_http (1.0.1)
28
+ faraday-net_http_persistent (1.2.0)
29
+ faraday-patron (1.0.0)
30
+ faraday-rack (1.0.0)
31
+ faraday_middleware (1.2.0)
32
+ faraday (~> 1.0)
33
+ multipart-post (2.1.1)
34
+ rake (13.0.6)
35
+ ruby2_keywords (0.0.5)
36
+
37
+ PLATFORMS
38
+ x86_64-linux
39
+
40
+ DEPENDENCIES
41
+ dotenv
42
+ rake (~> 13.0)
43
+ starlingrb!
44
+
45
+ BUNDLED WITH
46
+ 2.2.30
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Dean Perry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # StarlingRB
2
+
3
+ **This library is a work in progress**
4
+
5
+ StarlingRB is a Ruby library for interacting with the Starling Bank API.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem "starlingrb", require: "starling"
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Set Client Details
18
+
19
+ Firstly you'll need to set an Access Token.
20
+
21
+ ```ruby
22
+ @client = Starling::Client.new(access_token: "")
23
+ ```
24
+
25
+ ### Accounts
26
+
27
+ ```ruby
28
+ Starling::Account.list
29
+ Starling::Account.balance(account: "account_uid")
30
+ ```
31
+
32
+ ### Transactions
33
+
34
+ ```ruby
35
+ # from and to should be date time stamps
36
+ Starling::Transaction.list(account: "account_uid", from: Date.parse("2023-01-01").to_datetime, to: Date.today.to_datetime)
37
+ ```
38
+
39
+ ## Contributing
40
+
41
+ Bug reports and pull requests are welcome on GitHub at https://github.com/deanpcmad/starlingrb.
42
+
43
+ ## License
44
+
45
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
data/bin/console ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "starling"
6
+
7
+ # Load environment variables from .env file
8
+ require 'dotenv/load'
9
+
10
+ # You can add fixtures and/or initialization code here to make experimenting
11
+ # with your gem easier. You can also use a different console, if you like.
12
+
13
+ # (If you use this, don't forget to add pry to your Gemfile!)
14
+ # require "pry"
15
+ # Pry.start
16
+
17
+ Starling.configure do |config|
18
+ config.environment = :sandbox
19
+ config.access_token = ENV["STARLING_ACCESS_TOKEN"]
20
+ end
21
+
22
+ require "irb"
23
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,72 @@
1
+ module Starling
2
+ class Client
3
+
4
+ BASE_PRODUCTION_URL = "https://api.starlingbank.com/api/v2"
5
+ BASE_SANDBOX_URL = "https://api-sandbox.starlingbank.com/api/v2"
6
+
7
+ class << self
8
+
9
+ def connection
10
+ @connection ||= Faraday.new(Starling.config.url) do |conn|
11
+ conn.request :authorization, :Bearer, Starling.config.access_token
12
+ conn.request :json
13
+
14
+ conn.headers = {
15
+ "User-Agent" => "starlingrb/v#{VERSION} (github.com/deanpcmad/starlingrb)"
16
+ }
17
+
18
+ conn.response :dates
19
+ conn.response :json, content_type: "application/json"
20
+ end
21
+ end
22
+
23
+ def get_request(url, params: {}, headers: {})
24
+ handle_response connection.get(url, params, headers)
25
+ end
26
+
27
+ def post_request(url, body: {}, headers: {})
28
+ handle_response connection.post(url, body, headers)
29
+ end
30
+
31
+ def put_request(url, body:, headers: {})
32
+ handle_response connection.put(url, body, headers)
33
+ end
34
+
35
+ def patch_request(url, body:, headers: {})
36
+ handle_response connection.patch(url, body, headers)
37
+ end
38
+
39
+ def delete_request(url, headers: {})
40
+ handle_response connection.delete(url, headers)
41
+ end
42
+
43
+ def handle_response(response)
44
+ case response.status
45
+ when 400
46
+ raise Error, "Error 400: Your request was malformed. '#{response.body["error_description"]}'"
47
+ when 401
48
+ raise Error, "Error 401: You did not supply valid authentication credentials. '#{response.body["error_description"]}'"
49
+ when 403
50
+ raise Error, "Error 403: You are not allowed to perform that action. '#{response.body["error_description"]}'"
51
+ when 404
52
+ raise Error, "Error 404: No results were found for your request."
53
+ when 409
54
+ raise Error, "Error 409: Your request was a conflict. '#{response.body["error_description"]}'"
55
+ when 429
56
+ raise Error, "Error 429: Your request exceeded the API rate limit. '#{response.body["error_description"]}'"
57
+ when 500
58
+ raise Error, "Error 500: We were unable to perform the request due to server-side problems. '#{response.body["error_description"]}'"
59
+ when 503
60
+ raise Error, "Error 503: You have been rate limited for sending more than 20 requests per second. '#{response.body["error_description"]}'"
61
+ when 501
62
+ raise Error, "Error 501: This resource has not been implemented. '#{response.body["error_description"]}'"
63
+ when 204
64
+ return true
65
+ end
66
+
67
+ response
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,19 @@
1
+ module Starling
2
+ class Collection
3
+ attr_reader :data, :total
4
+
5
+ def self.from_response(response, type:, key:)
6
+ body = response.body
7
+
8
+ new(
9
+ data: body[key].map { |attrs| type.new(attrs) },
10
+ total: body[key].count
11
+ )
12
+ end
13
+
14
+ def initialize(data:, total:)
15
+ @data = data
16
+ @total = total
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Starling
4
+ class Configuration
5
+
6
+ attr_accessor :environment, :access_token
7
+
8
+ def url
9
+ if environment == :sandbox
10
+ Starling::Client::BASE_SANDBOX_URL
11
+ elsif environment == :production
12
+ Starling::Client::BASE_PRODUCTION_URL
13
+ else
14
+ nil
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,4 @@
1
+ module Starling
2
+ class Error < StandardError
3
+ end
4
+ end
@@ -0,0 +1,18 @@
1
+ module Starling
2
+ class Account < Object
3
+
4
+ class << self
5
+
6
+ def list
7
+ response = Client.get_request("accounts")
8
+ Collection.from_response(response, type: Account, key: "accounts")
9
+ end
10
+
11
+ def balance(account:)
12
+ Balance.new Client.get_request("accounts/#{account}/balance").body
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ module Starling
2
+ class AccountHoldersResource < Resource
3
+
4
+ def account_holder
5
+ AccountHolder.new get_request("account-holder").body
6
+ end
7
+
8
+ def name
9
+ AccountHolder.new get_request("account-holder/name").body
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ module Starling
2
+ class Balance < Object
3
+ end
4
+ end
@@ -0,0 +1,76 @@
1
+ module Starling
2
+ class Card < Object
3
+
4
+ class << self
5
+ def list
6
+ response = Client.get_request("cards")
7
+ Collection.from_response(response, type: Card, key: "cards")
8
+ end
9
+
10
+ # Enables or Disables a card
11
+ # Required scope: card-control:edit
12
+ def enabled(uid:, enabled:)
13
+ response = Client.put_request("cards/#{uid}/controls/enabled", body: {enabled: enabled})
14
+
15
+ return true if response.success?
16
+ end
17
+
18
+ # Enables or Disables ATM Withdrawal
19
+ # Required scope: card-control:edit
20
+ def atm_enabled(uid:, enabled:)
21
+ response = Client.put_request("cards/#{uid}/controls/atm-enabled", body: {enabled: enabled})
22
+
23
+ return true if response.success?
24
+ end
25
+
26
+ # Enables or Disables Gambling
27
+ # Required scope: card-control:edit
28
+ def gambling_enabled(uid:, enabled:)
29
+ response = Client.put_request("cards/#{uid}/controls/gambling-enabled", body: {enabled: enabled})
30
+
31
+ return true if response.success?
32
+ end
33
+
34
+ # Enables or Disables Mag Stripe
35
+ # Required scope: card-control:edit
36
+ def mag_stripe_enabled(uid:, enabled:)
37
+ response = Client.put_request("cards/#{uid}/controls/mag-stripe-enabled", body: {enabled: enabled})
38
+
39
+ return true if response.success?
40
+ end
41
+
42
+ # Enables or Disables Mobile Wallet
43
+ # Required scope: card-control:edit
44
+ def mobile_wallet_enabled(uid:, enabled:)
45
+ response = Client.put_request("cards/#{uid}/controls/mobile-wallet-enabled", body: {enabled: enabled})
46
+
47
+ return true if response.success?
48
+ end
49
+
50
+ # Enables or Disables Online
51
+ # Required scope: card-control:edit
52
+ def online_enabled(uid:, enabled:)
53
+ response = Client.put_request("cards/#{uid}/controls/online-enabled", body: {enabled: enabled})
54
+
55
+ return true if response.success?
56
+ end
57
+
58
+ # Enables or Disables POS (contactless & chip and pin)
59
+ # Required scope: card-control:edit
60
+ def pos_enabled(uid:, enabled:)
61
+ response = Client.put_request("cards/#{uid}/controls/pos-enabled", body: {enabled: enabled})
62
+
63
+ return true if response.success?
64
+ end
65
+
66
+ # Required scope: card-control:edit
67
+ def currency_switch(uid:, enabled:, currency:)
68
+ body = {enabled: enabled, currency: currency}
69
+ response = Client.put_request("cards/#{uid}/controls/currency-switch", body: body)
70
+
71
+ return true if response.success?
72
+ end
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,27 @@
1
+ module Starling
2
+ class DirectDebitMandatesResource < Resource
3
+
4
+ # Required scope: mandate:read
5
+ def list
6
+ response = get_request("direct-debit/mandates")
7
+ Collection.from_response(response, type: DirectDebitMandate, key: "mandates")
8
+ end
9
+
10
+ # Required scope: mandate:read
11
+ def retrieve(uid:)
12
+ DirectDebitMandate.new get_request("direct-debit/mandates/#{uid}").body
13
+ end
14
+
15
+ # Required scope: mandate:read
16
+ def payments(uid:, since:)
17
+ response = get_request("direct-debit/mandates/#{uid}/payments", params: {since: since})
18
+ Collection.from_response(response, type: DirectDebitPayment, key: "directDebitPayments")
19
+ end
20
+
21
+ # Required scope: mandate:delete
22
+ def cancel(uid:)
23
+ delete_request("direct-debit/mandates/#{uid}")
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ module Starling
2
+ class Transaction < Object
3
+
4
+ class << self
5
+
6
+ def list(account:, from:, to:)
7
+ params = {minTransactionTimestamp: from, maxTransactionTimestamp: to}
8
+ response = Client.get_request("feed/account/#{account}/settled-transactions-between", params: params)
9
+ Collection.from_response(response, type: Transaction, key: "feedItems")
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ require "ostruct"
2
+
3
+ module Starling
4
+ class Object < OpenStruct
5
+ def initialize(attributes)
6
+ super to_ostruct(attributes)
7
+ end
8
+
9
+ def to_ostruct(obj)
10
+ if obj.is_a?(Hash)
11
+ OpenStruct.new(obj.map { |key, val| [key, to_ostruct(val)] }.to_h)
12
+ elsif obj.is_a?(Array)
13
+ obj.map { |o| to_ostruct(o) }
14
+ else # Assumed to be a primitive value
15
+ obj
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Starling
4
+ VERSION = "0.1.0"
5
+ end
data/lib/starling.rb ADDED
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "faraday_middleware"
5
+
6
+ require_relative "starling/version"
7
+
8
+ module Starling
9
+
10
+ autoload :Configuration, "starling/configuration"
11
+ autoload :Client, "starling/client"
12
+ autoload :Collection, "starling/collection"
13
+ autoload :Error, "starling/error"
14
+ autoload :Object, "starling/object"
15
+
16
+ class << self
17
+ attr_writer :config
18
+ end
19
+
20
+ def self.configure
21
+ yield(config) if block_given?
22
+ end
23
+
24
+ def self.config
25
+ @config ||= Starling::Configuration.new
26
+ end
27
+
28
+ autoload :Account, "starling/models/account"
29
+ autoload :Card, "starling/models/card"
30
+ autoload :Transaction, "starling/models/transaction"
31
+
32
+ # Additional
33
+ autoload :Balance, "starling/models/balance"
34
+
35
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/starling/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "starlingrb"
7
+ spec.version = Starling::VERSION
8
+ spec.authors = ["Dean Perry"]
9
+ spec.email = ["dean@deanpcmad.com"]
10
+
11
+ spec.summary = "A Ruby library for interacting with the Starling Bank API"
12
+ spec.homepage = "https://deanpcmad.com"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 2.6.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/deanpcmad/starlingrb"
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
22
+ `git ls-files -z`.split("\x0").reject do |f|
23
+ (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
24
+ end
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_dependency "faraday", "~> 1.7"
31
+ spec.add_dependency "faraday_middleware", "~> 1.1"
32
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: starlingrb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dean Perry
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-05-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ description:
42
+ email:
43
+ - dean@deanpcmad.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".env.example"
49
+ - Gemfile
50
+ - Gemfile.lock
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - bin/console
55
+ - bin/setup
56
+ - lib/starling.rb
57
+ - lib/starling/client.rb
58
+ - lib/starling/collection.rb
59
+ - lib/starling/configuration.rb
60
+ - lib/starling/error.rb
61
+ - lib/starling/models/account.rb
62
+ - lib/starling/models/account_holders.rb
63
+ - lib/starling/models/balance.rb
64
+ - lib/starling/models/card.rb
65
+ - lib/starling/models/direct_debit_mandates.rb
66
+ - lib/starling/models/transaction.rb
67
+ - lib/starling/object.rb
68
+ - lib/starling/version.rb
69
+ - starlingrb.gemspec
70
+ homepage: https://deanpcmad.com
71
+ licenses:
72
+ - MIT
73
+ metadata:
74
+ homepage_uri: https://deanpcmad.com
75
+ source_code_uri: https://github.com/deanpcmad/starlingrb
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 2.6.0
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubygems_version: 3.5.9
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: A Ruby library for interacting with the Starling Bank API
95
+ test_files: []