kortana-dev-sdk 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 997d5b86ba941ebf76795917ab911e7db813ec8e761fb80f46ed06491d29f968
4
+ data.tar.gz: 10399a24ab1a9a28ab0797b548645cbcf8c5d56eccfc8f2554a34d50f725f048
5
+ SHA512:
6
+ metadata.gz: e0f3ad4b65934e278e02de90558c7072a42fe39e4e620c5756e703273b68851fbea01a818e160810ee30ea2a2bba9de70753c512f805b3a35c82c247d39246c7
7
+ data.tar.gz: b2dc9cfd6344c0a9dcb8d7be738a343463340a5185bbfaf0d30dba9b0c1c055580786a76cbc7a32a5a51e91f0e9f36354154c860bb171cfec151152d58f5786b
@@ -0,0 +1,131 @@
1
+ module Kortana
2
+ class Client
3
+ attr_reader :blockchain, :wallets, :contracts, :payments, :merchants,
4
+ :banking, :cards, :compliance, :settlement
5
+
6
+ BASE_URLS = {
7
+ "mainnet" => "https://console.kortana.network/api/v1",
8
+ "testnet" => "https://console.kortana.network/api/v1"
9
+ }.freeze
10
+
11
+ def initialize(api_key:, environment: "mainnet", base_url: nil, timeout: 30, max_retries: 3)
12
+ raise ConfigurationError, "api_key must not be empty" if api_key.nil? || api_key.strip.empty?
13
+ raise ConfigurationError, "environment must be 'mainnet' or 'testnet'" unless %w[mainnet testnet].include?(environment)
14
+
15
+ @api_key = api_key.strip
16
+ @environment = environment
17
+ @base_url = base_url || BASE_URLS[environment]
18
+ @timeout = timeout
19
+ @max_retries = max_retries
20
+
21
+ setup_http_client
22
+ setup_modules
23
+ end
24
+
25
+ def get(path, params = {}, headers = {})
26
+ request(:get, path, params, nil, headers)
27
+ end
28
+
29
+ def post(path, body = nil, headers = {})
30
+ request(:post, path, nil, body, headers)
31
+ end
32
+
33
+ def put(path, body = nil, headers = {})
34
+ request(:put, path, nil, body, headers)
35
+ end
36
+
37
+ def delete(path, headers = {})
38
+ request(:delete, path, nil, nil, headers)
39
+ end
40
+
41
+ private
42
+
43
+ def setup_http_client
44
+ @conn = Faraday.new(url: @base_url) do |f|
45
+ f.request :url_encoded
46
+
47
+ f.request :retry, {
48
+ max: @max_retries,
49
+ interval: 1.0,
50
+ backoff_factor: 2.0,
51
+ exceptions: [Faraday::ConnectionFailed, Faraday::TimeoutError]
52
+ }
53
+
54
+ f.options.timeout = @timeout
55
+ f.options.open_timeout = 5
56
+ f.adapter Faraday.default_adapter
57
+ end
58
+ end
59
+
60
+ def setup_modules
61
+ require_relative 'modules/blockchain'
62
+ require_relative 'modules/wallets'
63
+ require_relative 'modules/contracts'
64
+ require_relative 'modules/payments'
65
+ require_relative 'modules/merchants'
66
+ require_relative 'modules/banking'
67
+ require_relative 'modules/cards'
68
+ require_relative 'modules/compliance'
69
+ require_relative 'modules/settlement'
70
+
71
+ @blockchain = Modules::Blockchain.new(self)
72
+ @wallets = Modules::Wallets.new(self)
73
+ @contracts = Modules::Contracts.new(self)
74
+ @payments = Modules::Payments.new(self)
75
+ @merchants = Modules::Merchants.new(self)
76
+ @banking = Modules::Banking.new(self)
77
+ @cards = Modules::Cards.new(self)
78
+ @compliance = Modules::Compliance.new(self)
79
+ @settlement = Modules::Settlement.new(self)
80
+ end
81
+
82
+ def request(method, path, params = nil, body = nil, headers = {})
83
+ # Auto-generate idempotency key for mutations if write operation
84
+ idempotency_key = headers["Idempotency-Key"]
85
+ if %i[post put patch].include?(method) && !idempotency_key
86
+ idempotency_key = "idem_#{SecureRandom.uuid}"
87
+ end
88
+
89
+ res = @conn.send(method) do |req|
90
+ req.path = path
91
+ req.params = params if params
92
+ req.headers["Authorization"] = "Bearer #{@api_key}"
93
+ req.headers["User-Agent"] = "kortana-sdk-ruby/1.0.0"
94
+ req.headers["Idempotency-Key"] = idempotency_key if idempotency_key
95
+ req.headers["Content-Type"] = "application/json"
96
+ req.body = body.to_json if body
97
+ end
98
+
99
+ handle_response(res)
100
+ rescue Faraday::Error => e
101
+ raise ServerError.new("Network/Faraday connection failed: #{e.message}")
102
+ end
103
+
104
+ def handle_response(res)
105
+ return JSON.parse(res.body) if res.status >= 200 && res.status < 300
106
+
107
+ begin
108
+ err_body = JSON.parse(res.body)
109
+ err_detail = err_body["error"] || {}
110
+ msg = err_detail["message"] || "API returned status #{res.status}"
111
+ code = err_detail["code"]
112
+ request_id = err_detail["request_id"]
113
+ rescue
114
+ msg = "API returned status #{res.status}"
115
+ code = nil
116
+ request_id = nil
117
+ end
118
+
119
+ error_class = case res.status
120
+ when 401 then AuthError
121
+ when 400 then ValidationError
122
+ when 429 then RateLimitError
123
+ when 404 then NotFoundError
124
+ when 409 then ConflictError
125
+ else ServerError
126
+ end
127
+
128
+ raise error_class.new(msg, code: code, request_id: request_id, http_status: res.status)
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,23 @@
1
+ module Kortana
2
+ class Error < StandardError; end
3
+ class ConfigurationError < Error; end
4
+
5
+ class APIError < Error
6
+ attr_reader :code, :request_id, :http_status
7
+
8
+ def initialize(message, code: nil, request_id: nil, http_status: nil)
9
+ super(message)
10
+ @code = code
11
+ @request_id = request_id
12
+ @http_status = http_status
13
+ end
14
+ end
15
+
16
+ class AuthError < APIError; end
17
+ class ValidationError < APIError; end
18
+ class RateLimitError < APIError; end
19
+ class NotFoundError < APIError; end
20
+ class ConflictError < APIError; end
21
+ class ServerError < APIError; end
22
+ class WebhookSignatureError < Error; end
23
+ end
@@ -0,0 +1,61 @@
1
+ module Kortana
2
+ module Modules
3
+ class Banking
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def create_customer(name:, email:, phone: nil, address: nil)
9
+ @client.post("/banking/customers", {
10
+ name: name,
11
+ email: email,
12
+ phone: phone,
13
+ address: address
14
+ })
15
+ end
16
+
17
+ def get_customer(id)
18
+ @client.get("/banking/customers/#{id}")
19
+ end
20
+
21
+ def update_customer(id, params)
22
+ @client.put("/banking/customers/#{id}", params)
23
+ end
24
+
25
+ def list_customers(options = {})
26
+ @client.get("/banking/customers", options)
27
+ end
28
+
29
+ def create_bank_account(customer_id:, bank_name:, account_number:, routing_number:, account_type: "checking")
30
+ @client.post("/banking/accounts", {
31
+ customerId: customer_id,
32
+ bankName: bank_name,
33
+ accountNumber: account_number,
34
+ routingNumber: routing_number,
35
+ accountType: account_type
36
+ })
37
+ end
38
+
39
+ def get_bank_account(id)
40
+ @client.get("/banking/accounts/#{id}")
41
+ end
42
+
43
+ def list_bank_accounts(customer_id)
44
+ @client.get("/banking/accounts", { customerId: customer_id })
45
+ end
46
+
47
+ def create_transfer(from_address:, to_address:, amount:, currency: "USD")
48
+ @client.post("/banking/transfers", {
49
+ fromAddress: from_address,
50
+ toAddress: to_address,
51
+ amount: amount.to_s,
52
+ currency: currency
53
+ })
54
+ end
55
+
56
+ def get_transfer(id)
57
+ @client.get("/banking/transfers/#{id}")
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,48 @@
1
+ module Kortana
2
+ module Modules
3
+ class Blockchain
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def get_block(block_number_or_hash)
9
+ @client.get("/blockchain/blocks/#{block_number_or_hash}")
10
+ end
11
+
12
+ def get_transaction(tx_hash)
13
+ @client.get("/blockchain/transactions/#{tx_hash}")
14
+ end
15
+
16
+ def get_transaction_receipt(tx_hash)
17
+ @client.get("/blockchain/transactions/#{tx_hash}/receipt")
18
+ end
19
+
20
+ def get_gas_price
21
+ res = @client.get("/blockchain/gas-price")
22
+ res["gasPrice"].to_i
23
+ end
24
+
25
+ def estimate_gas(params)
26
+ res = @client.post("/blockchain/estimate-gas", params)
27
+ res["gasLimit"].to_i
28
+ end
29
+
30
+ def get_network_status
31
+ @client.get("/blockchain/status")
32
+ end
33
+
34
+ def get_logs(filter)
35
+ @client.post("/blockchain/logs", filter)
36
+ end
37
+
38
+ def get_validators
39
+ @client.get("/blockchain/validators")
40
+ end
41
+
42
+ def get_token_balance(address, token_address)
43
+ res = @client.get("/blockchain/addresses/#{address}/token-balance", { token: token_address })
44
+ res["balance"].to_i
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,48 @@
1
+ module Kortana
2
+ module Modules
3
+ class Cards
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def create(customer_id: nil, merchant_id: nil, type: "virtual", currency: "DNR", spend_limit: nil, metadata: nil)
9
+ @client.post("/cards", {
10
+ customerId: customer_id,
11
+ merchantId: merchant_id,
12
+ type: type,
13
+ currency: currency,
14
+ spendLimit: spend_limit ? spend_limit.to_s : nil,
15
+ metadata: metadata
16
+ })
17
+ end
18
+
19
+ def get(id)
20
+ @client.get("/cards/#{id}")
21
+ end
22
+
23
+ def list(options = {})
24
+ @client.get("/cards", options)
25
+ end
26
+
27
+ def update_controls(id, controls)
28
+ @client.put("/cards/#{id}/controls", controls)
29
+ end
30
+
31
+ def disable(id)
32
+ @client.post("/cards/#{id}/disable")
33
+ end
34
+
35
+ def enable(id)
36
+ @client.post("/cards/#{id}/enable")
37
+ end
38
+
39
+ def simulate_transaction(card_id:, amount:, merchant: nil)
40
+ @client.post("/cards/simulate", {
41
+ cardId: card_id,
42
+ amount: amount.to_s,
43
+ merchant: merchant
44
+ })
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,61 @@
1
+ module Kortana
2
+ module Modules
3
+ class Compliance
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def create_kyc(customer_id: nil, merchant_id: nil, document_type:, document_country:, document_front:, document_back: nil, selfie: nil)
9
+ @client.post("/compliance/kyc", {
10
+ customerId: customer_id,
11
+ merchantId: merchant_id,
12
+ documentType: document_type,
13
+ documentCountry: document_country,
14
+ documentFront: document_front,
15
+ documentBack: document_back,
16
+ selfie: selfie
17
+ })
18
+ end
19
+
20
+ def get_kyc(id)
21
+ @client.get("/compliance/kyc/#{id}")
22
+ end
23
+
24
+ def create_kyb(merchant_id:, business_name:, business_type:, tax_id: nil, documents: nil)
25
+ @client.post("/compliance/kyb", {
26
+ merchantId: merchant_id,
27
+ businessName: business_name,
28
+ businessType: business_type,
29
+ taxId: tax_id,
30
+ documents: documents
31
+ })
32
+ end
33
+
34
+ def get_kyb(id)
35
+ @client.get("/compliance/kyb/#{id}")
36
+ end
37
+
38
+ def screen(entity_id: nil, transaction_id: nil, first_name: nil, last_name: nil, dob: nil)
39
+ @client.post("/compliance/screen", {
40
+ entityId: entity_id,
41
+ transactionId: transaction_id,
42
+ firstName: first_name,
43
+ lastName: last_name,
44
+ dob: dob
45
+ })
46
+ end
47
+
48
+ def get_screening(id)
49
+ @client.get("/compliance/screen/#{id}")
50
+ end
51
+
52
+ def create_str(transaction_id:, reason:, evidence: nil)
53
+ @client.post("/compliance/str", {
54
+ transactionId: transaction_id,
55
+ reason: reason,
56
+ evidence: evidence
57
+ })
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,62 @@
1
+ module Kortana
2
+ module Modules
3
+ class Contracts
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def deploy_contract(abi:, bytecode:, args: nil)
9
+ @client.post("/contracts/deploy", {
10
+ abi: abi,
11
+ bytecode: bytecode,
12
+ args: args
13
+ })
14
+ end
15
+
16
+ def read_contract(address, abi, method, args = [])
17
+ res = @client.post("/contracts/#{address}/read", {
18
+ abi: abi,
19
+ method: method,
20
+ args: args
21
+ })
22
+ res["result"]
23
+ end
24
+
25
+ def write_contract(address, abi, method, args = [], options = {})
26
+ @client.post("/contracts/#{address}/write", {
27
+ abi: abi,
28
+ method: method,
29
+ args: args,
30
+ options: options
31
+ })
32
+ end
33
+
34
+ def estimate_contract_gas(address, abi, method, args = [], options = {})
35
+ res = @client.post("/contracts/#{address}/estimate-gas", {
36
+ abi: abi,
37
+ method: method,
38
+ args: args,
39
+ options: options
40
+ })
41
+ res["gasLimit"].to_i
42
+ end
43
+
44
+ def get_contract_events(address, abi, event_name, filter = {})
45
+ @client.post("/contracts/#{address}/events", {
46
+ abi: abi,
47
+ eventName: event_name,
48
+ filter: filter
49
+ })
50
+ end
51
+
52
+ def verify_contract(address, source_code:, compiler_version:, optimizer: false, optimizer_runs: 200)
53
+ @client.post("/contracts/#{address}/verify", {
54
+ sourceCode: source_code,
55
+ compilerVersion: compiler_version,
56
+ optimizer: optimizer,
57
+ optimizerRuns: optimizer_runs
58
+ })
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,62 @@
1
+ module Kortana
2
+ module Modules
3
+ class Merchants
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def create(name:, email:, business_name: nil, metadata: nil)
9
+ @client.post("/merchants", {
10
+ name: name,
11
+ email: email,
12
+ businessName: business_name,
13
+ metadata: metadata
14
+ })
15
+ end
16
+
17
+ def get(id)
18
+ @client.get("/merchants/#{id}")
19
+ end
20
+
21
+ def update(id, params)
22
+ @client.put("/merchants/#{id}", params)
23
+ end
24
+
25
+ def list_stores(merchant_id)
26
+ @client.get("/merchants/#{merchant_id}/stores")
27
+ end
28
+
29
+ def create_store(merchant_id, name:, currency: "DNR", settlement_currency: "DNR")
30
+ @client.post("/merchants/#{merchant_id}/stores", {
31
+ name: name,
32
+ currency: currency,
33
+ settlementCurrency: settlement_currency
34
+ })
35
+ end
36
+
37
+ def list_terminals(merchant_id)
38
+ @client.get("/merchants/#{merchant_id}/terminals")
39
+ end
40
+
41
+ def create_terminal(merchant_id, name: nil, store_id: nil, location: nil)
42
+ @client.post("/merchants/#{merchant_id}/terminals", {
43
+ name: name,
44
+ storeId: store_id,
45
+ location: location
46
+ })
47
+ end
48
+
49
+ def create_api_key(merchant_id, name:, permissions:, expires_at: nil)
50
+ @client.post("/merchants/#{merchant_id}/api-keys", {
51
+ name: name,
52
+ permissions: permissions,
53
+ expiresAt: expires_at
54
+ })
55
+ end
56
+
57
+ def list_api_keys(merchant_id)
58
+ @client.get("/merchants/#{merchant_id}/api-keys")
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,60 @@
1
+ module Kortana
2
+ module Modules
3
+ class Payments
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def create_intent(amount:, currency: "DNR", description: nil, customer_id: nil, merchant_id: nil, metadata: nil)
9
+ @client.post("/payments/intents", {
10
+ amount: amount.to_s,
11
+ currency: currency,
12
+ description: description,
13
+ customerId: customer_id,
14
+ merchantId: merchant_id,
15
+ metadata: metadata
16
+ })
17
+ end
18
+
19
+ def get_intent(id)
20
+ @client.get("/payments/intents/#{id}")
21
+ end
22
+
23
+ def confirm_intent(id, payment_method = nil)
24
+ @client.post("/payments/intents/#{id}/confirm", {
25
+ paymentMethod: payment_method
26
+ })
27
+ end
28
+
29
+ def cancel_intent(id)
30
+ @client.post("/payments/intents/#{id}/cancel")
31
+ end
32
+
33
+ def create_invoice(items:, customer: nil, due_date: nil, metadata: nil)
34
+ @client.post("/payments/invoices", {
35
+ items: items,
36
+ customer: customer,
37
+ dueDate: due_date,
38
+ metadata: metadata
39
+ })
40
+ end
41
+
42
+ def get_invoice(id)
43
+ @client.get("/payments/invoices/#{id}")
44
+ end
45
+
46
+ def create_payment_link(amount:, currency: "DNR", description: nil, expires_at: nil)
47
+ @client.post("/payments/links", {
48
+ amount: amount.to_s,
49
+ currency: currency,
50
+ description: description,
51
+ expiresAt: expires_at
52
+ })
53
+ end
54
+
55
+ def get_payment_link(id)
56
+ @client.get("/payments/links/#{id}")
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,22 @@
1
+ module Kortana
2
+ module Modules
3
+ class Settlement
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def get_treasury(currency: nil)
9
+ params = currency ? { currency: currency } : {}
10
+ @client.get("/settlement/treasury", params)
11
+ end
12
+
13
+ def list(options = {})
14
+ @client.get("/settlement/settlements", options)
15
+ end
16
+
17
+ def get(id)
18
+ @client.get("/settlement/settlements/#{id}")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,39 @@
1
+ module Kortana
2
+ module Modules
3
+ class Wallets
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def get_balance
9
+ @client.get("/wallets/balance")
10
+ end
11
+
12
+ def list_addresses
13
+ @client.get("/wallets/addresses")
14
+ end
15
+
16
+ def get_address(index = nil)
17
+ params = index ? { index: index } : {}
18
+ @client.get("/wallets/address", params)
19
+ end
20
+
21
+ def transfer(to:, amount:, currency: "DNR", chain: nil)
22
+ @client.post("/wallets/transfers", {
23
+ to: to,
24
+ amount: amount.to_s,
25
+ currency: currency,
26
+ chain: chain
27
+ })
28
+ end
29
+
30
+ def list_transactions(options = {})
31
+ @client.get("/wallets/transactions", options)
32
+ end
33
+
34
+ def get_transaction(id)
35
+ @client.get("/wallets/transactions/#{id}")
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module Kortana
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,33 @@
1
+ module Kortana
2
+ class Webhook
3
+ def initialize(secret)
4
+ @secret = secret
5
+ end
6
+
7
+ def verify(payload, signature)
8
+ raise WebhookSignatureError, "Signature must not be empty" if signature.nil? || signature.strip.empty?
9
+ raise WebhookSignatureError, "Webhook secret must not be empty" if @secret.nil? || @secret.strip.empty?
10
+
11
+ expected = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @secret, payload)
12
+
13
+ unless secure_compare(expected, signature)
14
+ raise WebhookSignatureError, "Webhook signature verification failed"
15
+ end
16
+
17
+ JSON.parse(payload)
18
+ rescue JSON::ParserError
19
+ raise WebhookSignatureError, "Invalid JSON payload"
20
+ end
21
+
22
+ private
23
+
24
+ # Constant time comparison to avoid timing attacks
25
+ def secure_compare(a, b)
26
+ return false unless a.bytesize == b.bytesize
27
+ l = a.unpack("C*")
28
+ res = 0
29
+ b.each_byte { |val| res |= val ^ l.shift }
30
+ res.zero?
31
+ end
32
+ end
33
+ end
data/lib/kortana.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'faraday'
2
+ require 'faraday/retry'
3
+ require 'json'
4
+ require 'openssl'
5
+ require 'securerandom'
6
+
7
+ require_relative 'kortana/version'
8
+ require_relative 'kortana/errors'
9
+ require_relative 'kortana/client'
10
+ require_relative 'kortana/webhooks'
11
+
12
+ module Kortana
13
+ # Entry point configuration module
14
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kortana-dev-sdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Kortana Labs
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: faraday
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.8'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.8'
26
+ - !ruby/object:Gem::Dependency
27
+ name: faraday-retry
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.2'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.2'
40
+ description: Integrate with Kortana Pay, wallets, smart contracts, card issuance,
41
+ compliance, and ledger APIs directly from Ruby applications.
42
+ email:
43
+ - engineering@kortana.io
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/kortana.rb
49
+ - lib/kortana/client.rb
50
+ - lib/kortana/errors.rb
51
+ - lib/kortana/modules/banking.rb
52
+ - lib/kortana/modules/blockchain.rb
53
+ - lib/kortana/modules/cards.rb
54
+ - lib/kortana/modules/compliance.rb
55
+ - lib/kortana/modules/contracts.rb
56
+ - lib/kortana/modules/merchants.rb
57
+ - lib/kortana/modules/payments.rb
58
+ - lib/kortana/modules/settlement.rb
59
+ - lib/kortana/modules/wallets.rb
60
+ - lib/kortana/version.rb
61
+ - lib/kortana/webhooks.rb
62
+ homepage: https://docs.kortana.io/sdk/ruby
63
+ licenses:
64
+ - MIT
65
+ metadata:
66
+ homepage_uri: https://docs.kortana.io/sdk/ruby
67
+ source_code_uri: https://gitlab.com/emeka.iwuagwu/kortanablockchain-hub
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubygems_version: 4.0.10
83
+ specification_version: 4
84
+ summary: Official Ruby SDK for the Kortana Blockchain Platform
85
+ test_files: []