tangany 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.reek.yml +4 -0
  3. data/.rspec +3 -0
  4. data/.rubycritic.yml +7 -0
  5. data/.sasori/Dockerfile +51 -0
  6. data/.simplecov +13 -0
  7. data/CHANGELOG.md +5 -0
  8. data/CODE_OF_CONDUCT.md +84 -0
  9. data/Gemfile +20 -0
  10. data/Gemfile.lock +210 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +410 -0
  13. data/Rakefile +133 -0
  14. data/bin/console +22 -0
  15. data/bin/setup +8 -0
  16. data/bin/test-live +170 -0
  17. data/lib/config/chains.json +22 -0
  18. data/lib/tangany/application_contract.rb +19 -0
  19. data/lib/tangany/collection.rb +13 -0
  20. data/lib/tangany/config.rb +24 -0
  21. data/lib/tangany/custody/client.rb +37 -0
  22. data/lib/tangany/custody/collection.rb +17 -0
  23. data/lib/tangany/custody/contracts/wallets/create.rb +23 -0
  24. data/lib/tangany/custody/contracts/wallets/list.rb +37 -0
  25. data/lib/tangany/custody/contracts/wallets/update.rb +21 -0
  26. data/lib/tangany/custody/contracts/wallets.rb +3 -0
  27. data/lib/tangany/custody/contracts.rb +1 -0
  28. data/lib/tangany/custody/objects/wallet.rb +17 -0
  29. data/lib/tangany/custody/objects/wallet_recovery.rb +10 -0
  30. data/lib/tangany/custody/objects/wallet_status.rb +10 -0
  31. data/lib/tangany/custody/objects.rb +3 -0
  32. data/lib/tangany/custody/resource.rb +29 -0
  33. data/lib/tangany/custody/resources/wallet_statuses_resource.rb +9 -0
  34. data/lib/tangany/custody/resources/wallets_resource.rb +34 -0
  35. data/lib/tangany/custody/resources.rb +2 -0
  36. data/lib/tangany/custody.rb +7 -0
  37. data/lib/tangany/customers/application_contract.rb +6 -0
  38. data/lib/tangany/customers/client.rb +37 -0
  39. data/lib/tangany/customers/collection.rb +16 -0
  40. data/lib/tangany/customers/contracts/customers/create.rb +17 -0
  41. data/lib/tangany/customers/contracts/customers/create_schemas/contract.rb +21 -0
  42. data/lib/tangany/customers/contracts/customers/create_schemas/customer.rb +34 -0
  43. data/lib/tangany/customers/contracts/customers/list.rb +17 -0
  44. data/lib/tangany/customers/contracts/customers/update.rb +14 -0
  45. data/lib/tangany/customers/contracts/customers/update_schemas/customer.rb +15 -0
  46. data/lib/tangany/customers/contracts/customers.rb +3 -0
  47. data/lib/tangany/customers/contracts/natural_persons/create.rb +23 -0
  48. data/lib/tangany/customers/contracts/natural_persons/create_schemas/address.rb +23 -0
  49. data/lib/tangany/customers/contracts/natural_persons/create_schemas/document.rb +25 -0
  50. data/lib/tangany/customers/contracts/natural_persons/create_schemas/kyc.rb +24 -0
  51. data/lib/tangany/customers/contracts/natural_persons/create_schemas/natural_person.rb +44 -0
  52. data/lib/tangany/customers/contracts/natural_persons/create_schemas/pep.rb +22 -0
  53. data/lib/tangany/customers/contracts/natural_persons/create_schemas/sanctions.rb +22 -0
  54. data/lib/tangany/customers/contracts/natural_persons/list.rb +17 -0
  55. data/lib/tangany/customers/contracts/natural_persons/update.rb +14 -0
  56. data/lib/tangany/customers/contracts/natural_persons/update_schemas/natural_person.rb +15 -0
  57. data/lib/tangany/customers/contracts/natural_persons.rb +3 -0
  58. data/lib/tangany/customers/contracts/wallet_links/create.rb +28 -0
  59. data/lib/tangany/customers/contracts/wallet_links/list.rb +17 -0
  60. data/lib/tangany/customers/contracts/wallet_links.rb +2 -0
  61. data/lib/tangany/customers/contracts.rb +3 -0
  62. data/lib/tangany/customers/objects/address.rb +11 -0
  63. data/lib/tangany/customers/objects/contract.rb +13 -0
  64. data/lib/tangany/customers/objects/customer.rb +14 -0
  65. data/lib/tangany/customers/objects/document.rb +17 -0
  66. data/lib/tangany/customers/objects/kyc.rb +16 -0
  67. data/lib/tangany/customers/objects/natural_person.rb +30 -0
  68. data/lib/tangany/customers/objects/pep.rb +12 -0
  69. data/lib/tangany/customers/objects/sanctions.rb +12 -0
  70. data/lib/tangany/customers/objects/wallet_link.rb +14 -0
  71. data/lib/tangany/customers/objects.rb +5 -0
  72. data/lib/tangany/customers/resource.rb +11 -0
  73. data/lib/tangany/customers/resources/customers_resource.rb +27 -0
  74. data/lib/tangany/customers/resources/natural_persons_resource.rb +26 -0
  75. data/lib/tangany/customers/resources/wallet_links_resource.rb +37 -0
  76. data/lib/tangany/customers/resources.rb +3 -0
  77. data/lib/tangany/customers.rb +8 -0
  78. data/lib/tangany/error.rb +34 -0
  79. data/lib/tangany/json_patch.rb +65 -0
  80. data/lib/tangany/object.rb +43 -0
  81. data/lib/tangany/operation.rb +10 -0
  82. data/lib/tangany/resource.rb +80 -0
  83. data/lib/tangany/types.rb +7 -0
  84. data/lib/tangany/version.rb +3 -0
  85. data/lib/tangany.rb +47 -0
  86. data/sig/tangany.rbs +4 -0
  87. metadata +217 -0
data/bin/test-live ADDED
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ puts "This suite will run tests against the \e[1mlive Tangany's API\e[0m."
4
+ puts "\e[36mBe sure to set environment variables with \e[1mtesting values\e[0m\e[36m before running this suite.\e[0m"
5
+ print "Do you want to continue? [y/N] "
6
+ answer = gets.chomp
7
+
8
+ exit 1 unless answer == "y"
9
+
10
+ require "bundler/setup"
11
+ require "byebug"
12
+ require "factory_bot"
13
+
14
+ require "tangany"
15
+
16
+ load("Rakefile")
17
+ Rake::Task["regenerate_fixtures"].invoke
18
+
19
+ Tangany.client_id = ENV.fetch("TEST_TANGANY_CLIENT_ID", "test")
20
+ Tangany.client_secret = ENV.fetch("TEST_TANGANY_CLIENT_SECRET", "test")
21
+ Tangany.environment = "testnet"
22
+ Tangany.subscription = ENV.fetch("TEST_TANGANY_SUBSCRIPTION", "test")
23
+ Tangany.vault_url = ENV.fetch("TEST_TANGANY_VAULT_URL", "test")
24
+
25
+ def safe_not_found(&block)
26
+ yield
27
+ rescue Tangany::RequestError => e
28
+ raise e unless e.status_code == 404
29
+ end
30
+
31
+ begin
32
+ custody_client = Tangany::Custody::Client.new
33
+ customers_client = Tangany::Customers::Client.new
34
+
35
+ puts
36
+ puts "== Preparing data ".ljust(80, "=")
37
+ inputs = {
38
+ customer: {
39
+ create: JSON.parse(
40
+ File.read("spec/fixtures/generated/inputs/customers/customers/create/valid_input.json"),
41
+ symbolize_names: true
42
+ ),
43
+ update: JSON.parse(
44
+ File.read("spec/fixtures/generated/inputs/customers/customers/update/valid_input.json"),
45
+ symbolize_names: true
46
+ )
47
+ },
48
+ natural_person: {
49
+ create: JSON.parse(
50
+ File.read("spec/fixtures/generated/inputs/customers/natural_persons/create/valid_input.json"),
51
+ symbolize_names: true
52
+ ),
53
+ update: JSON.parse(
54
+ File.read("spec/fixtures/generated/inputs/customers/natural_persons/update/valid_input.json"),
55
+ symbolize_names: true
56
+ )
57
+ },
58
+ wallet: {
59
+ create: JSON.parse(
60
+ File.read("spec/fixtures/generated/inputs/custody/wallets/create/valid_input.json"),
61
+ symbolize_names: true
62
+ )
63
+ },
64
+ wallet_link: {
65
+ create: JSON.parse(
66
+ File.read("spec/fixtures/generated/inputs/customers/wallet_links/create/valid_input.json"),
67
+ symbolize_names: true
68
+ )
69
+ }
70
+ }
71
+ ids = {
72
+ customer: inputs[:customer][:create][:id],
73
+ natural_person: inputs[:natural_person][:create][:id],
74
+ wallet: inputs[:wallet][:create][:wallet],
75
+ wallet_link: inputs[:wallet_link][:create][:id]
76
+ }
77
+ inputs[:customer][:create][:owner][:entityId] = ids[:natural_person]
78
+ inputs[:customer][:create][:authorized][0][:entityId] = ids[:natural_person]
79
+ inputs[:customer][:update][:id] = ids[:customer]
80
+ inputs[:customer][:update][:owner][:entityId] = ids[:natural_person]
81
+ inputs[:customer][:update][:authorized][0][:entityId] = ids[:natural_person]
82
+ inputs[:natural_person][:update][:id] = ids[:natural_person]
83
+ inputs[:wallet_link][:create][:assignment][:customerId] = ids[:customer]
84
+ inputs[:wallet_link][:create][:assetId] = "ETH"
85
+ puts " -> \e[36mCustomer: \e[1m#{ids[:customer]}\e[0m"
86
+ puts " -> \e[36mNatural person: \e[1m#{ids[:natural_person]}\e[0m"
87
+ puts " -> \e[36mWallet: \e[1m#{ids[:wallet]}\e[0m"
88
+ puts " -> \e[36mWallet link: \e[1m#{ids[:wallet_link]}\e[0m"
89
+ puts "== Data prepared ".ljust(80, "=")
90
+
91
+ puts
92
+ puts "== Running tests... ".ljust(80, "=")
93
+
94
+ puts " -> Creating natural person..."
95
+ natural_person = customers_client.natural_persons.create(inputs[:natural_person][:create])
96
+ raise "Natural person creation failed" unless natural_person.is_a?(Tangany::Customers::NaturalPerson)
97
+
98
+ puts " -> Listing natural persons..."
99
+ natural_persons = customers_client.natural_persons.list
100
+ raise "Natural person not present in list" unless natural_persons.data.map(&:id).include?(ids[:natural_person])
101
+
102
+ puts " -> Retrieving natural person..."
103
+ natural_person = customers_client.natural_persons.retrieve(ids[:natural_person])
104
+ raise "Natural person retrieval failed" unless natural_person.is_a?(Tangany::Customers::NaturalPerson)
105
+
106
+ puts " -> Updating natural person..."
107
+ natural_person = customers_client.natural_persons.update(ids[:natural_person], inputs[:natural_person][:update])
108
+ raise "Natural person update failed" unless natural_person.is_a?(Tangany::Customers::NaturalPerson)
109
+
110
+ puts " -> Creating customer..."
111
+ customer = customers_client.customers.create(inputs[:customer][:create])
112
+ raise "Customer creation failed" unless customer.is_a?(Tangany::Customers::Customer)
113
+
114
+ puts " -> Listing customers..."
115
+ customers = customers_client.customers.list
116
+ raise "Customer not present in list" unless customers.data.map(&:id).include?(ids[:customer])
117
+
118
+ puts " -> Retrieving customer..."
119
+ customer = customers_client.customers.retrieve(ids[:customer])
120
+ raise "Customer retrieval failed" unless customer.is_a?(Tangany::Customers::Customer)
121
+
122
+ puts " -> Updating customer..."
123
+ customer = customers_client.customers.update(ids[:customer], inputs[:customer][:update])
124
+ raise "Customer update failed" unless customer.is_a?(Tangany::Customers::Customer)
125
+
126
+ puts " -> Creating wallet..."
127
+ wallet = custody_client.wallets.create(inputs[:wallet][:create])
128
+ raise "Wallet creation failed" unless wallet.is_a?(Tangany::Custody::Wallet)
129
+
130
+ puts " -> Creating wallet link with address value..."
131
+ wallet_link = customers_client.wallet_links.create(inputs[:wallet_link][:create])
132
+ raise "Wallet link creation failed" unless wallet_link.is_a?(Tangany::Customers::WalletLink)
133
+
134
+ puts " -> Creating wallet link with wallet value..."
135
+ customers_client.wallet_links.delete(ids[:wallet_link])
136
+ inputs[:wallet_link][:create].delete(:address)
137
+ inputs[:wallet_link][:create][:wallet] = ids[:wallet]
138
+ wallet_link = customers_client.wallet_links.create(inputs[:wallet_link][:create])
139
+ raise "Wallet link creation failed" unless wallet_link.is_a?(Tangany::Customers::WalletLink)
140
+
141
+ puts " -> Listing wallet links..."
142
+ wallet_links = customers_client.wallet_links.list
143
+ raise "Wallet link not present in list" unless wallet_links.data.map(&:id).include?(ids[:wallet_link])
144
+
145
+ puts " -> Retrieving wallet link..."
146
+ wallet_link = customers_client.wallet_links.retrieve(ids[:wallet_link])
147
+ raise "Wallet link retrieval failed" unless wallet_link.is_a?(Tangany::Customers::WalletLink)
148
+
149
+ puts "== Tests run... ".ljust(80, "=")
150
+ rescue => e
151
+ puts e.message
152
+ exit 1
153
+ ensure
154
+ puts
155
+ puts "== Cleaning up... ".ljust(80, "=")
156
+
157
+ puts " -> Deleting wallet link..."
158
+ safe_not_found { customers_client.wallet_links.delete(ids[:wallet_link]) }
159
+
160
+ puts " -> Deleting wallet..."
161
+ safe_not_found { custody_client.wallets.delete(ids[:wallet]) }
162
+
163
+ puts " -> Deleting customer..."
164
+ safe_not_found { customers_client.customers.delete(ids[:customer]) }
165
+
166
+ puts " -> Deleting natural person..."
167
+ safe_not_found { customers_client.natural_persons.delete(ids[:natural_person]) }
168
+
169
+ puts "== Cleaned ".ljust(80, "=")
170
+ end
@@ -0,0 +1,22 @@
1
+ [
2
+ {
3
+ "asset_id": "ETH",
4
+ "base_path": "eth",
5
+ "header": {
6
+ "name": "tangany-ethereum-network",
7
+ "mainnet": "mainnet",
8
+ "testnet": "goerli"
9
+ },
10
+ "name": "Ethereum"
11
+ },
12
+ {
13
+ "asset_id": "MATIC",
14
+ "base_path": "eth",
15
+ "header": {
16
+ "name": "tangany-ethereum-network",
17
+ "mainnet": "polygon",
18
+ "testnet": "https://rpc-mumbai.maticvigil.com"
19
+ },
20
+ "name": "Polygon"
21
+ }
22
+ ]
@@ -0,0 +1,19 @@
1
+ require "active_support/core_ext/object/to_param"
2
+ require "dry-validation"
3
+
4
+ module Tangany
5
+ class ApplicationContract < Dry::Validation::Contract
6
+ ALLOWED_SORTS = ["asc", "desc"].freeze
7
+ COUNTRY_CODE_REGEX = %r{[A-Z]{2}}
8
+ DATE_REGEX = %r{[0-9]{4}-[0-9]{2}-[0-9]{2}}
9
+ DATETIME_REGEX = %r{[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z}
10
+ ETHEREUM_ADDRESS_REGEX = %r{^0x[a-fA-F0-9]{40}$}
11
+
12
+ def to_safe_params!(params)
13
+ response = call(params)
14
+ raise InputError, response.errors.to_h if response.failure?
15
+
16
+ response.to_h
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module Tangany
2
+ class Collection
3
+ attr_reader :data, :next_page_token, :next_path, :previous_path, :total
4
+
5
+ def initialize(data:, total:, next_page_token: nil, next_path: nil, previous_path: nil)
6
+ @data = data
7
+ @next_page_token = next_page_token
8
+ @next_path = next_path
9
+ @previous_path = previous_path
10
+ @total = total
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ require "json"
2
+
3
+ module Tangany
4
+ class Config
5
+ attr_accessor :client_id, :client_secret, :environment, :chain, :subscription, :vault_url
6
+
7
+ attr_reader :custody_base_url, :customers_base_url, :customers_version, :chains
8
+
9
+ def initialize
10
+ @custody_base_url = "https://api.tangany.com/v1"
11
+
12
+ @customers_base_url = "https://api.tangany.com/customers"
13
+ @customers_version = "1"
14
+
15
+ @chains = load_chains
16
+ end
17
+
18
+ private
19
+
20
+ def load_chains
21
+ JSON.parse(File.read(File.join(__dir__, "../config/chains.json")))
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,37 @@
1
+ require "faraday"
2
+
3
+ module Tangany
4
+ module Custody
5
+ class Client
6
+ attr_reader :adapter, :client_id, :client_secret, :environment, :subscription, :vault_url
7
+
8
+ def initialize(adapter: Faraday.default_adapter, stubs: nil)
9
+ @adapter = adapter
10
+ @client_id = Tangany.client_id
11
+ @client_secret = Tangany.client_secret
12
+ @environment = Tangany.environment
13
+ @subscription = Tangany.subscription
14
+ @vault_url = Tangany.vault_url
15
+
16
+ @stubs = stubs
17
+ end
18
+
19
+ def connection
20
+ @connection ||= Faraday.new do |faraday|
21
+ faraday.adapter(adapter, @stubs)
22
+ faraday.request(:json)
23
+ faraday.response(:json, content_type: /\bjson$/, parser_options: {symbolize_names: true})
24
+ faraday.url_prefix = Tangany.custody_base_url
25
+ end
26
+ end
27
+
28
+ def wallets
29
+ WalletsResource.new(self)
30
+ end
31
+
32
+ def wallet_statuses(asset_id:)
33
+ WalletStatusesResource.new(self, asset_id: asset_id)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ module Tangany
2
+ module Custody
3
+ class Collection
4
+ class << self
5
+ def from_response(response, type:)
6
+ body = response.body
7
+ Tangany::Collection.new(
8
+ data: body[:list].map { |attributes| type.new(attributes) },
9
+ total: body.dig(:hits, :total),
10
+ next_path: body.dig(:links, :next),
11
+ previous_path: body.dig(:links, :previous)
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ module Tangany
2
+ module Custody
3
+ module Contracts
4
+ module Wallets
5
+ class Create < ApplicationContract
6
+ TagSchema = Dry::Schema.Params do
7
+ 10.times do |i|
8
+ optional("tag#{i}".to_sym).maybe(:string, max_size?: 256)
9
+ end
10
+ end
11
+
12
+ schema do
13
+ config.validate_keys = true
14
+
15
+ optional(:wallet).filled(:string, max_size?: 127, min_size?: 1)
16
+ optional(:useHsm).filled(:bool)
17
+ optional(:tags).array(TagSchema)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ module Tangany
2
+ module Custody
3
+ module Contracts
4
+ module Wallets
5
+ class List < ApplicationContract
6
+ ALLOWED_ORDERS = ["created", "security", "updated", "wallet"].freeze
7
+
8
+ schema do
9
+ config.validate_keys = true
10
+
11
+ optional(:start).filled(:integer, lt?: 10_000)
12
+ optional(:limit).filled(:integer, gt?: 0, lteq?: 100)
13
+ optional(:order).filled(:string, included_in?: ALLOWED_ORDERS)
14
+ optional(:sort).filled(:string, included_in?: ALLOWED_SORTS)
15
+ optional(:tags).filled(:array, min_size?: 1)
16
+ optional(:xtags).filled(:array, min_size?: 1)
17
+ end
18
+
19
+ rule(:sort) do
20
+ key.failure("should not be specified without `order`") if values[:sort] && values[:order].nil?
21
+ end
22
+
23
+ def to_safe_params!(params)
24
+ safe_params = super(params)
25
+ order = safe_params.delete(:order)
26
+
27
+ safe_params[:sort] = order + ((safe_params[:sort] == "desc") ? "desc" : "") if order
28
+ safe_params[:index] = safe_params.delete(:start) if safe_params[:start]
29
+ safe_params[:tags] = safe_params[:tags].join(",") if safe_params[:tags]
30
+ safe_params[:xtags] = safe_params[:xtags].join(",") if safe_params[:xtags]
31
+ safe_params
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,21 @@
1
+ module Tangany
2
+ module Custody
3
+ module Contracts
4
+ module Wallets
5
+ class Update < ApplicationContract
6
+ TagSchema = Dry::Schema.Params do
7
+ 10.times do |i|
8
+ optional("tag#{i}".to_sym).maybe(:string, max_size?: 256)
9
+ end
10
+ end
11
+
12
+ schema do
13
+ config.validate_keys = true
14
+
15
+ optional(:tags).array(TagSchema)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ require_relative "wallets/create"
2
+ require_relative "wallets/list"
3
+ require_relative "wallets/update"
@@ -0,0 +1 @@
1
+ require_relative "contracts/wallets"
@@ -0,0 +1,17 @@
1
+ module Tangany
2
+ module Custody
3
+ class Wallet < Object
4
+ attribute :wallet, Types::String
5
+ attribute? :version, Types::String
6
+ attribute? :created, Types::DateTime
7
+ attribute? :updated, Types::DateTime
8
+ attribute? :security, Types::String
9
+ attribute? :public do
10
+ attribute :secp256k1, Types::String
11
+ end
12
+ attribute? :tags, Types::Array
13
+
14
+ to_datetime :created, :updated
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ module Tangany
2
+ module Custody
3
+ class WalletRecovery < Object
4
+ attribute :recoveryId, Types::String
5
+ attribute :scheduledPurgeDate, Types::DateTime
6
+
7
+ to_datetime :scheduledPurgeDate
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Tangany
2
+ module Custody
3
+ class WalletStatus < Object
4
+ attribute :address, Types::String
5
+ attribute :balance, Types::String
6
+ attribute :currency, Types::String
7
+ attribute :nonce, Types::Integer
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ require_relative "objects/wallet"
2
+ require_relative "objects/wallet_status"
3
+ require_relative "objects/wallet_recovery"
@@ -0,0 +1,29 @@
1
+ module Tangany
2
+ module Custody
3
+ class Resource < Tangany::Resource
4
+ def initialize(client, options = {})
5
+ @chain = Tangany.chains.find { |chain| chain["asset_id"] == options[:asset_id] } if options[:asset_id]
6
+
7
+ super(client)
8
+ end
9
+
10
+ private
11
+
12
+ def default_headers
13
+ headers = {
14
+ "tangany-client-id" => client.client_id,
15
+ "tangany-client-secret" => client.client_secret,
16
+ "tangany-subscription" => client.subscription,
17
+ "tangany-vault-url" => client.vault_url
18
+ }
19
+ merge_chain_header(headers) if @chain
20
+ headers
21
+ end
22
+
23
+ def merge_chain_header(headers)
24
+ header = @chain["header"]
25
+ headers.merge(header["name"] => header[Tangany.environment])
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ module Tangany
2
+ module Custody
3
+ class WalletStatusesResource < Resource
4
+ def retrieve(wallet_id)
5
+ WalletStatus.new(get_request("#{@chain["base_path"]}/wallet/#{wallet_id}").body)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ module Tangany
2
+ module Custody
3
+ class WalletsResource < Resource
4
+ def create(**params)
5
+ Wallet.new(post_request("wallets", body: sanitize_params!(params).to_json).body)
6
+ end
7
+
8
+ def delete(wallet_id)
9
+ WalletRecovery.new(delete_request("wallet/#{wallet_id}").body)
10
+ end
11
+
12
+ def list(**params)
13
+ Collection.from_response(get_request("wallets", params: sanitize_params!(params)), type: Wallet)
14
+ end
15
+
16
+ def retrieve(wallet_id)
17
+ Wallet.new(get_request("wallet/#{wallet_id}").body)
18
+ end
19
+
20
+ def update(wallet_id, **params)
21
+ safe_params = sanitize_params!(params)
22
+
23
+ retrieve_response = get_request("wallet/#{wallet_id}")
24
+ wallet = Wallet.new(retrieve_response.body)
25
+
26
+ Wallet.new(patch_request(
27
+ "wallet/#{wallet_id}",
28
+ body: build_update_body_json(wallet.to_h, safe_params),
29
+ headers: {"If-Match" => retrieve_response.headers["If-Match"]}
30
+ ).body)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,2 @@
1
+ require_relative "resources/wallet_statuses_resource"
2
+ require_relative "resources/wallets_resource"
@@ -0,0 +1,7 @@
1
+ require_relative "custody/client"
2
+ require_relative "custody/collection"
3
+ require_relative "custody/resource"
4
+
5
+ require_relative "custody/contracts"
6
+ require_relative "custody/objects"
7
+ require_relative "custody/resources"
@@ -0,0 +1,6 @@
1
+ module Tangany
2
+ module Customers
3
+ class ApplicationContract < Tangany::ApplicationContract
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,37 @@
1
+ require "faraday"
2
+
3
+ module Tangany
4
+ module Customers
5
+ class Client
6
+ attr_reader :adapter, :subscription
7
+
8
+ def initialize(adapter: Faraday.default_adapter, stubs: nil)
9
+ @adapter = adapter
10
+ @subscription = Tangany.subscription
11
+
12
+ @stubs = stubs
13
+ end
14
+
15
+ def connection
16
+ @connection ||= Faraday.new do |faraday|
17
+ faraday.adapter(adapter, @stubs)
18
+ faraday.request(:json)
19
+ faraday.response(:json, content_type: /\bjson$/, parser_options: {symbolize_names: true})
20
+ faraday.url_prefix = Tangany.customers_base_url
21
+ end
22
+ end
23
+
24
+ def customers
25
+ CustomersResource.new(self)
26
+ end
27
+
28
+ def natural_persons
29
+ NaturalPersonsResource.new(self)
30
+ end
31
+
32
+ def wallet_links
33
+ WalletLinksResource.new(self)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,16 @@
1
+ module Tangany
2
+ module Customers
3
+ class Collection
4
+ class << self
5
+ def from_response(response, type:)
6
+ body = response.body
7
+ Tangany::Collection.new(
8
+ data: body[:items].map { |attributes| type.new(attributes) },
9
+ total: body.dig(:pageInfo, :totalResults),
10
+ next_page_token: body[:nextPageToken]
11
+ )
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ require_relative "create_schemas/customer"
2
+
3
+ module Tangany
4
+ module Customers
5
+ module Contracts
6
+ module Customers
7
+ class Create < ApplicationContract
8
+ schema(CreateSchemas::Customer.schema) { config.validate_keys = true }
9
+
10
+ rule(:contracts) do
11
+ key.failure("must contain at least one contract") if value.size == 0
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Tangany
2
+ module Customers
3
+ module Contracts
4
+ module Customers
5
+ module CreateSchemas
6
+ module Contract
7
+ class << self
8
+ def schema
9
+ Dry::Schema.Params do
10
+ required(:type).filled(:string, included_in?: Tangany::Customers::Contract::ALLOWED_TYPES)
11
+ required(:signedDate).filled(:string, format?: ApplicationContract::DATE_REGEX)
12
+ optional(:cancelledDate).maybe(:string, format?: ApplicationContract::DATE_REGEX)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ require_relative "contract"
2
+
3
+ module Tangany
4
+ module Customers
5
+ module Contracts
6
+ module Customers
7
+ module CreateSchemas
8
+ module Customer
9
+ module ClassMethods
10
+ def schema
11
+ Dry::Schema.Params do
12
+ required(:id).filled(:string, max_size?: 40)
13
+ required(:owner).hash do
14
+ required(:entityId).filled(:string)
15
+ end
16
+ required(:authorized).array(:hash) do
17
+ required(:entityId).filled(:string)
18
+ end
19
+ required(:contracts).array(CreateSchemas::Contract.schema)
20
+ end
21
+ end
22
+ end
23
+
24
+ extend ClassMethods
25
+
26
+ def self.included(base)
27
+ base.extend(ClassMethods)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end