blnk 0.1.1 → 0.1.3
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 +4 -4
- data/README.md +47 -20
- data/lib/blnk/balance.rb +9 -3
- data/lib/blnk/ledger.rb +9 -3
- data/lib/blnk/resourceable.rb +110 -20
- data/lib/blnk/transaction.rb +64 -0
- data/lib/blnk/version.rb +1 -1
- data/lib/blnk.rb +3 -0
- metadata +45 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c5fd560be10539e1da9ac8d3d47685a4070b2723432ef1b2580ae5e57760a82
|
4
|
+
data.tar.gz: d90db62cdd4fbea9c633cdbe579df1e3242188b520b9e4de17e095b201a598fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8e50a2169fe30914d20bd8bab234202900e23d336215c93e643edb34ced8a0565996aa7fe873b10a90862ed5b17e1915191b92367bc616c6ff42560b63acd81
|
7
|
+
data.tar.gz: 81c7c8d09fcaf7312e3fb256a5d7a991c59e0c1355141ff8487df32544a40716a11f33ea72909c964a1a3fb437d2aaf6510ef7ededf6481b8c4cc75917dafbb6
|
data/README.md
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# This gem is under development, don't use in production
|
2
|
-
|
3
1
|
# Blnk
|
4
2
|
|
5
3
|
Easy way to use the blnkfinance.com API in ruby
|
@@ -14,23 +12,40 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
14
12
|
|
15
13
|
$ gem install blnk
|
16
14
|
|
17
|
-
##
|
15
|
+
## TODO
|
18
16
|
|
19
|
-
TODO:
|
20
17
|
- [x] Create Ledger
|
21
18
|
- [x] Find Ledger
|
22
19
|
- [x] List Ledgers
|
23
|
-
- [
|
20
|
+
- [x] Search Ledgers
|
24
21
|
- [x] Create Balances
|
25
22
|
- [x] Find Balance
|
26
|
-
- [
|
27
|
-
- [
|
28
|
-
- [
|
29
|
-
- [
|
23
|
+
- [x] Search Balances
|
24
|
+
- [x] Create Transaction
|
25
|
+
- [x] Multiple sources / destinations Transaction
|
26
|
+
- [x] Refund Transaction
|
27
|
+
- [x] Commit inflight Transaction
|
28
|
+
- [x] Void inflight Transaction
|
29
|
+
- [x] Find Transaction
|
30
|
+
- [x] Search Transactions
|
31
|
+
- [ ] Handler notifications
|
32
|
+
- [ ] Create Balance Monitor
|
33
|
+
- [ ] Find Balance Monitor
|
34
|
+
- [ ] Update Balance Monitor
|
35
|
+
- [ ] Backup endpoint
|
36
|
+
- [ ] Backup to S3 endpoint
|
37
|
+
- [ ] Add Search Contract schema for each resource using they own search attributes
|
38
|
+
- [ ] Search Result should convert document resul into resource class
|
39
|
+
- [x] Use Dry Monads to get success / failure output
|
40
|
+
- [x] Use Dry Validation to validate inputs
|
41
|
+
- [ ] Use Dry Schema instead OpenStruct to handle with resource attributes
|
42
|
+
- [ ] Use Dry Configuration to better config DSL
|
30
43
|
|
31
44
|
## Usage
|
32
45
|
|
33
46
|
```ruby
|
47
|
+
transaction = Blnk::Transaction.find 'transaction_id'
|
48
|
+
|
34
49
|
require 'blnk'
|
35
50
|
|
36
51
|
# client config
|
@@ -39,28 +54,40 @@ Blnk.address = '192.168.2.7:5001'
|
|
39
54
|
Blnk.secret_token = 'your_strong_secret_key'
|
40
55
|
Blnk.search_api_key = Blnk.secret_token
|
41
56
|
|
42
|
-
#
|
57
|
+
# Ledgers
|
43
58
|
|
44
59
|
ledger = Blnk::Ledger.create(name: 'foobar')
|
45
60
|
ledger = Blnk::Ledger.find 'ledger_id'
|
46
61
|
ledgers = Blnk::Ledger.all
|
47
62
|
|
48
|
-
|
49
|
-
ledgers = Blnk::Ledger.search(
|
50
|
-
q: 'USD',
|
51
|
-
filter_by: 'balances > 1400',
|
52
|
-
sort_by: 'created_at:desc',
|
53
|
-
page: 1,
|
54
|
-
per_page: 50
|
55
|
-
)
|
56
|
-
|
63
|
+
ledgers = Blnk::Ledger.search(q: '*')
|
57
64
|
|
58
|
-
#
|
65
|
+
# Balances
|
59
66
|
balance = Blnk::Balance.find 'balance_id'
|
60
67
|
balance = Blnk::Balance.create(ledger_id: 'ledger_id', currency: 'USD')
|
61
68
|
|
69
|
+
balances = Blnk::Balance.search(q: '*')
|
70
|
+
|
71
|
+
# Transactions
|
72
|
+
transaction = Blnk::Transaction.find 'transaction_id'
|
73
|
+
transaction = Blnk::Transaction.create(
|
74
|
+
amount: 75,
|
75
|
+
reference: 'ref_005',
|
76
|
+
currency: 'BRLX',
|
77
|
+
precision: 100,
|
78
|
+
source: '@world',
|
79
|
+
destination: 'bln_469f93bc-40e9-4e0e-b6ab-d11c3638c15d',
|
80
|
+
description: 'For fees',
|
81
|
+
allow_overdraft: true
|
82
|
+
)
|
83
|
+
|
84
|
+
transaction = Blnk::Transaction.search q: '*'
|
62
85
|
```
|
63
86
|
|
87
|
+
## Result
|
88
|
+
|
89
|
+
All methods return a Dry::Monad::Result, so you can use ```.failure?``` to check if method was executed and returned a failure (can be validation or a server error). ```.success?``` to check if method was executed with successful and access the data from the failure or successful result using ```.value!```. You can check on the dry-monad gem to see other options on Result.
|
90
|
+
|
64
91
|
|
65
92
|
## Development
|
66
93
|
|
data/lib/blnk/balance.rb
CHANGED
@@ -3,9 +3,15 @@
|
|
3
3
|
module Blnk
|
4
4
|
# Balance representation
|
5
5
|
class Balance < Resourceable
|
6
|
-
|
6
|
+
class CreateContract < Dry::Validation::Contract
|
7
|
+
schema do
|
8
|
+
required(:ledger_id).value(:string)
|
9
|
+
required(:currency).value(:string)
|
10
|
+
end
|
11
|
+
end
|
7
12
|
|
8
|
-
|
9
|
-
|
13
|
+
self.resource_name = :balances
|
14
|
+
self.id_field = :balance_id
|
15
|
+
self.create_contract = CreateContract
|
10
16
|
end
|
11
17
|
end
|
data/lib/blnk/ledger.rb
CHANGED
@@ -3,9 +3,15 @@
|
|
3
3
|
module Blnk
|
4
4
|
# Ledger representation
|
5
5
|
class Ledger < Resourceable
|
6
|
-
|
6
|
+
class CreateContract < Dry::Validation::Contract
|
7
|
+
schema do
|
8
|
+
required(:name).value(:string)
|
9
|
+
optional(:meta_data).value(:hash)
|
10
|
+
end
|
11
|
+
end
|
7
12
|
|
8
|
-
|
9
|
-
|
13
|
+
self.resource_name = :ledgers
|
14
|
+
self.id_field = :ledger_id
|
15
|
+
self.create_contract = CreateContract
|
10
16
|
end
|
11
17
|
end
|
data/lib/blnk/resourceable.rb
CHANGED
@@ -3,37 +3,127 @@
|
|
3
3
|
module Blnk
|
4
4
|
# Resoureable module that bring some tweaks for basic REST api integration
|
5
5
|
class Resourceable < OpenStruct
|
6
|
-
|
6
|
+
extend Client
|
7
|
+
extend Forwardable
|
7
8
|
|
8
|
-
|
9
|
+
def_delegators :'self.class', :put_request, :post_request, :get_request, :with_handler
|
9
10
|
|
10
|
-
|
11
|
-
response = new.get_request(path: "/#{resource_name}/#{id}")
|
12
|
-
return response unless response.status.success?
|
11
|
+
class SearchResult < OpenStruct; end
|
13
12
|
|
14
|
-
|
13
|
+
class DefaultSearchContract < Dry::Validation::Contract
|
14
|
+
schema do
|
15
|
+
required(:q).value(:string)
|
16
|
+
end
|
15
17
|
end
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
class << self
|
20
|
+
include Dry::Monads[:result]
|
21
|
+
|
22
|
+
attr_accessor :resource_name, :id_field, :create_contract, :search_contract
|
23
|
+
|
24
|
+
def resources_path = "/#{resource_name}"
|
25
|
+
def resource_path(id) = "/#{resource_name}/#{id}"
|
26
|
+
def search_path = "/search/#{resource_name}"
|
27
|
+
|
28
|
+
def find(id) = with_handler resp: find_request(id)
|
29
|
+
def find_request(id) = get_request(path: resource_path(id))
|
30
|
+
|
31
|
+
def all
|
32
|
+
check_vars
|
33
|
+
resp = get_request(path: resources_path)
|
34
|
+
with_handler(resp:, block: method(:all_handler))
|
35
|
+
end
|
36
|
+
|
37
|
+
def create(**args)
|
38
|
+
wrap_call(create_contract_new, args) do |contract|
|
39
|
+
with_handler(resp: post_request(path: resources_path, body: contract.to_h))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def search(**args)
|
44
|
+
wrap_call(search_contract_new, args) do |contract|
|
45
|
+
with_handler(resp: post_request(path: search_path, body: contract.to_h),
|
46
|
+
block: method(:search_handler))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_vars
|
51
|
+
raise NotImplementedError, 'missing self.resource_name' unless resource_name
|
52
|
+
raise NotImplementedError, 'missing self.id_field' unless id_field
|
53
|
+
raise NotImplementedError, 'missing self.create_contract' unless create_contract
|
54
|
+
end
|
55
|
+
|
56
|
+
def wrap_call(contract, args)
|
57
|
+
check_vars
|
58
|
+
ccall = contract.call(args)
|
59
|
+
return Failure(ccall.errors.to_h) if ccall.failure?
|
60
|
+
|
61
|
+
return yield ccall if block_given?
|
62
|
+
|
63
|
+
ccall
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_contract_new
|
67
|
+
return create_contract.new if create_contract
|
20
68
|
|
21
|
-
|
22
|
-
|
69
|
+
raise NotImplementedError, 'missing self.create_contract'
|
70
|
+
end
|
71
|
+
|
72
|
+
def search_contract_new = (search_contract || DefaultSearchContract).new
|
73
|
+
|
74
|
+
def search_handler(parsed, status)
|
75
|
+
success = status.success?
|
76
|
+
result = SearchResult.new(parsed) if success
|
77
|
+
|
78
|
+
inj_handler(result:, success:, error: parsed)
|
79
|
+
end
|
80
|
+
|
81
|
+
def all_handler(parsed, status)
|
82
|
+
success = status.success?
|
83
|
+
result = parsed.map { |r| new(r) } if success
|
84
|
+
inj_handler(success:, result:, error: parsed)
|
85
|
+
end
|
86
|
+
|
87
|
+
def handler(parsed, status)
|
88
|
+
inj_handler(
|
89
|
+
result: new(parsed),
|
90
|
+
error: parsed,
|
91
|
+
success: status.success?
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
def inj_handler(result:, error:, success:)
|
96
|
+
(success ? Success(result) : Failure(error))
|
97
|
+
end
|
98
|
+
|
99
|
+
def with_handler(resp:, kself: nil, block: method(:handler))
|
100
|
+
using_resp(resp:, kself:, &block)
|
101
|
+
end
|
102
|
+
|
103
|
+
def using_resp(resp:, kself: nil, &block)
|
104
|
+
check_vars
|
105
|
+
parsed = resp.parse
|
106
|
+
parsed = parsed.transform_keys(&:to_sym) unless parsed.is_a?(Array)
|
107
|
+
|
108
|
+
kself&.reload
|
109
|
+
|
110
|
+
block.call(parsed, resp.status)
|
23
111
|
end
|
24
112
|
end
|
25
113
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
body: new(*).body_data
|
30
|
-
)
|
31
|
-
return response unless response.status.success?
|
114
|
+
def reload
|
115
|
+
self.class.find_request(_id).tap do |res|
|
116
|
+
next unless res.status.success?
|
32
117
|
|
33
|
-
|
118
|
+
res.parse.each_pair do |k, v|
|
119
|
+
self[k] = v
|
120
|
+
end
|
121
|
+
end
|
122
|
+
self
|
34
123
|
end
|
35
124
|
|
36
|
-
|
37
|
-
def
|
125
|
+
# table[self.class.id_field]
|
126
|
+
def persisted? = !_id.nil?
|
127
|
+
def _id = public_send(self.class.id_field)
|
38
128
|
end
|
39
129
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Blnk
|
4
|
+
# Transaction representation
|
5
|
+
class Transaction < Resourceable
|
6
|
+
class CreateContract < Dry::Validation::Contract
|
7
|
+
schema do
|
8
|
+
required(:amount).value(:integer)
|
9
|
+
required(:precision).value(:integer)
|
10
|
+
required(:currency).value(:string)
|
11
|
+
required(:reference).value(:string)
|
12
|
+
optional(:source).value(:string)
|
13
|
+
optional(:sources).array(:hash) do
|
14
|
+
required(:identifier).value(:string)
|
15
|
+
required(:distribution).value(:string)
|
16
|
+
required(:narration).value(:string)
|
17
|
+
end
|
18
|
+
optional(:destination).value(:string)
|
19
|
+
optional(:destinations).array(:hash) do
|
20
|
+
required(:identifier).value(:string)
|
21
|
+
required(:distribution).value(:string)
|
22
|
+
required(:narration).value(:string)
|
23
|
+
end
|
24
|
+
required(:description).value(:string)
|
25
|
+
required(:allow_overdraft).value(:bool)
|
26
|
+
optional(:inflight).value(:bool)
|
27
|
+
optional(:rate).value(:integer)
|
28
|
+
optional(:scheduled_for).value(:string)
|
29
|
+
end
|
30
|
+
|
31
|
+
rule do
|
32
|
+
base.failure('must only contain one of source, sources') if key?(:source) && key?(:sources)
|
33
|
+
|
34
|
+
if key?(:destination) && key?(:destinations)
|
35
|
+
base.failure('must only contain one of destination, destinations')
|
36
|
+
end
|
37
|
+
|
38
|
+
if values[:source].to_s.empty? && values[:sources].to_s.empty?
|
39
|
+
key(:source).failure('missing source')
|
40
|
+
end
|
41
|
+
|
42
|
+
if values[:destination].to_s.empty? && values[:destinations].to_s.empty?
|
43
|
+
key(:destination).failure('missing destination')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
self.resource_name = :transactions
|
49
|
+
self.id_field = :transaction_id
|
50
|
+
self.create_contract = CreateContract
|
51
|
+
|
52
|
+
def refund = short_hander(resp: req_refund)
|
53
|
+
def void = short_hander(resp: req_inflight(body: { status: 'void' }))
|
54
|
+
def commit = short_hander(resp: req_inflight(body: { status: 'commit' }))
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def short_hander(resp:) = with_handler(resp:, kself: self)
|
59
|
+
def inflight_path = "/transactions/inflight/#{_id}"
|
60
|
+
def refund_path = "/refund-transaction/#{_id}"
|
61
|
+
def req_inflight(body:) = put_request(path: inflight_path, body:)
|
62
|
+
def req_refund = post_request(path: refund_path, body: nil)
|
63
|
+
end
|
64
|
+
end
|
data/lib/blnk/version.rb
CHANGED
data/lib/blnk.rb
CHANGED
@@ -2,11 +2,14 @@
|
|
2
2
|
|
3
3
|
require 'http'
|
4
4
|
require 'ostruct'
|
5
|
+
require 'dry-validation'
|
6
|
+
require 'dry/monads'
|
5
7
|
require_relative 'blnk/version'
|
6
8
|
require_relative 'blnk/client'
|
7
9
|
require_relative 'blnk/resourceable'
|
8
10
|
require_relative 'blnk/ledger'
|
9
11
|
require_relative 'blnk/balance'
|
12
|
+
require_relative 'blnk/transaction'
|
10
13
|
|
11
14
|
module Blnk
|
12
15
|
class Error < StandardError; end
|
metadata
CHANGED
@@ -1,15 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blnk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Antonio Roberto Silva
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06
|
11
|
+
date: 2024-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-configurable
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-monads
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-validation
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.10.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.10.0
|
13
55
|
- !ruby/object:Gem::Dependency
|
14
56
|
name: http
|
15
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -41,6 +83,7 @@ files:
|
|
41
83
|
- lib/blnk/client.rb
|
42
84
|
- lib/blnk/ledger.rb
|
43
85
|
- lib/blnk/resourceable.rb
|
86
|
+
- lib/blnk/transaction.rb
|
44
87
|
- lib/blnk/version.rb
|
45
88
|
- sig/blnk.rbs
|
46
89
|
homepage: https://blnkledger.com/
|