cryptoprocessing 0.6.1

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 (67) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +35 -0
  3. data/.coveralls.yml +1 -0
  4. data/.document +5 -0
  5. data/.editorconfig +12 -0
  6. data/.gemtest +0 -0
  7. data/.gitattributes +1 -0
  8. data/.gitignore +129 -0
  9. data/.hound.yml +5 -0
  10. data/.rspec +3 -0
  11. data/.rubocop.yml +65 -0
  12. data/.rubocop_todo.yml +0 -0
  13. data/.ruby-version +1 -0
  14. data/.simplecov +8 -0
  15. data/.travis.yml +11 -0
  16. data/.yardopts +10 -0
  17. data/CHANGELOG.md +12 -0
  18. data/CODE_OF_CONDUCT.md +74 -0
  19. data/Gemfile +6 -0
  20. data/Gemfile.lock +94 -0
  21. data/LICENSE.txt +21 -0
  22. data/NOTICE.txt +2 -0
  23. data/README.md +86 -0
  24. data/Rakefile +21 -0
  25. data/VERSION +1 -0
  26. data/bin/console +14 -0
  27. data/bin/setup +8 -0
  28. data/cryptoprocessing.gemspec +39 -0
  29. data/exe/cryptoprocessing +5 -0
  30. data/lib/cryptoprocessing.rb +37 -0
  31. data/lib/cryptoprocessing/adapters/em_http.rb +71 -0
  32. data/lib/cryptoprocessing/adapters/net_http.rb +6 -0
  33. data/lib/cryptoprocessing/authentication.rb +67 -0
  34. data/lib/cryptoprocessing/authentication/storages/file_token_store.rb +0 -0
  35. data/lib/cryptoprocessing/authentication/storages/redis_token_store.rb +0 -0
  36. data/lib/cryptoprocessing/authentication/token_store.rb +57 -0
  37. data/lib/cryptoprocessing/cli.rb +203 -0
  38. data/lib/cryptoprocessing/client.rb +108 -0
  39. data/lib/cryptoprocessing/client/accounts.rb +43 -0
  40. data/lib/cryptoprocessing/client/addresses.rb +56 -0
  41. data/lib/cryptoprocessing/client/api_errors.rb +7 -0
  42. data/lib/cryptoprocessing/client/api_response.rb +39 -0
  43. data/lib/cryptoprocessing/client/callbacks.rb +39 -0
  44. data/lib/cryptoprocessing/client/coinbase_wallet.rb +45 -0
  45. data/lib/cryptoprocessing/client/net_response.rb +100 -0
  46. data/lib/cryptoprocessing/client/trackers.rb +37 -0
  47. data/lib/cryptoprocessing/client/transactions.rb +90 -0
  48. data/lib/cryptoprocessing/configurable.rb +73 -0
  49. data/lib/cryptoprocessing/connection.rb +140 -0
  50. data/lib/cryptoprocessing/default.rb +78 -0
  51. data/lib/cryptoprocessing/error.rb +3 -0
  52. data/lib/cryptoprocessing/models/account.rb +39 -0
  53. data/lib/cryptoprocessing/models/address.rb +17 -0
  54. data/lib/cryptoprocessing/models/api_object.rb +14 -0
  55. data/lib/cryptoprocessing/models/callback.rb +4 -0
  56. data/lib/cryptoprocessing/models/tracker.rb +4 -0
  57. data/lib/cryptoprocessing/models/transaction.rb +6 -0
  58. data/lib/cryptoprocessing/models/user.rb +6 -0
  59. data/lib/cryptoprocessing/rails.rb +13 -0
  60. data/lib/cryptoprocessing/version.rb +17 -0
  61. data/script/bootstrap +5 -0
  62. data/script/cibuild +5 -0
  63. data/script/console +11 -0
  64. data/script/package +7 -0
  65. data/script/release +16 -0
  66. data/script/test +17 -0
  67. metadata +236 -0
@@ -0,0 +1,39 @@
1
+ require 'cryptoprocessing/models/callback'
2
+
3
+ module Cryptoprocessing
4
+ class Client
5
+ module Callbacks
6
+ # Callback list
7
+ #
8
+ # @param [String] account_id
9
+ # @return [Array<Cryptoprocessing::Callback>]
10
+ # @see https://api.cryptoprocessing.io/#e8bbf0e7-38e7-3e98-17f5-04733f419242
11
+ def callbacks(account_id, options = {})
12
+ out = nil
13
+ currency = if options[:currency] then options[:currency] else blockchain_type end
14
+ get("/v1/#{currency}/accounts/#{account_id}/callback", options) do |resp|
15
+ out = resp.data['addresses'].map { |item| Cryptoprocessing::Callback.new(self, item) }
16
+ yield(out, resp) if block_given?
17
+ end
18
+ out
19
+ end
20
+
21
+ # Create callback
22
+ #
23
+ # @param [String] account_id
24
+ # @param [String] address URL for callback
25
+ # @return [Cryptoprocessing::Callback]
26
+ # @see https://api.cryptoprocessing.io/#62b671c8-ba1c-5101-37a8-1ddf3dafb758
27
+ def create_callback(account_id, address, options = {})
28
+ out = nil
29
+ currency = if options[:currency] then options[:currency] else blockchain_type end
30
+ options[:address] = address
31
+ post("/v1/#{currency}/accounts/#{account_id}/callback", options) do |resp|
32
+ out = Cryptoprocessing::Callback.new(self, resp.body.merge(options))
33
+ yield(out, resp) if block_given?
34
+ end
35
+ out
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,45 @@
1
+ module Cryptoprocessing
2
+ class Client
3
+ ##
4
+ # Mimic Coinbase Wallet Client
5
+ #
6
+ module CoinbaseWallet
7
+ ##
8
+ #
9
+ #
10
+ def primary_account
11
+
12
+ end
13
+
14
+ # ##
15
+ # #
16
+ # #
17
+ # def create_address(options)
18
+ # @client.create_address(options)
19
+ # end
20
+
21
+ ##
22
+ #
23
+ #
24
+ def address_transactions(account_uid, address_uid, params = {})
25
+ list_transactions = []
26
+
27
+ @client.address_transactions(account_uid, address_uid) do |data, resp|
28
+ data.each do |tx|
29
+ if tx['confirmations_count'] > 3 && tx['type'] == 'send'
30
+ list_transactions.append(tx)
31
+ end
32
+ end
33
+ end
34
+ list_transactions
35
+ end
36
+
37
+ ##
38
+ #
39
+ #
40
+ def accounts
41
+ []
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,100 @@
1
+ require 'cryptoprocessing/client/api_response'
2
+ require 'cryptoprocessing/client/api_errors'
3
+
4
+ module Cryptoprocessing
5
+ # Net-Http response object
6
+ class NetHTTPResponse < APIResponse
7
+ def body
8
+ JSON.parse(@response.body) rescue {}
9
+ end
10
+
11
+ def body=(body)
12
+ @response.body = body.to_json
13
+ end
14
+
15
+ def data
16
+ body
17
+ end
18
+
19
+ def headers
20
+ out = @response.to_hash.map do |key, val|
21
+ [key.upcase.gsub('_', '-'), val.count == 1 ? val.first : val]
22
+ end
23
+ out.to_h
24
+ end
25
+
26
+ def status
27
+ @response.code.to_i
28
+ end
29
+ end
30
+
31
+ def self.check_response_status(resp)
32
+ if resp.status == 200 && resp.body.kind_of?(Array)
33
+ return
34
+ end
35
+
36
+ (resp.body['warnings'] || []).each do |warning|
37
+ message = "WARNING: #{warning['message']}"
38
+ message += " (#{warning['url']})" if warning["url"]
39
+ $stderr.puts message
40
+ end
41
+
42
+ # OAuth2 errors
43
+ if resp.status >= 400 && resp.body['error']
44
+ raise Cryptoprocessing::APIError, resp.body['error_description']
45
+ end
46
+
47
+ # Regular errors
48
+ if resp.body['errors']
49
+ case resp.status
50
+ when 400
51
+ case resp.body['errors'].first['id']
52
+ when 'param_required' then
53
+ raise ParamRequiredError, format_error(resp)
54
+ when 'invalid_request' then
55
+ raise InvalidRequestError, format_error(resp)
56
+ when 'personal_details_required' then
57
+ raise PersonalDetailsRequiredError, format_error(resp)
58
+ end
59
+ raise BadRequestError, format_error(resp)
60
+ when 401
61
+ case resp.body['errors'].first['id']
62
+ when 'authentication_error' then
63
+ raise AuthenticationError, format_error(resp)
64
+ when 'unverified_email' then
65
+ raise UnverifiedEmailError, format_error(resp)
66
+ when 'invalid_token' then
67
+ raise InvalidTokenError, format_error(resp)
68
+ when 'revoked_token' then
69
+ raise RevokedTokenError, format_error(resp)
70
+ when 'expired_token' then
71
+ raise ExpiredTokenError, format_error(resp)
72
+ end
73
+ raise AuthenticationError, format_error(resp)
74
+ when 402 then
75
+ raise TwoFactorRequiredError, format_error(resp)
76
+ when 403 then
77
+ raise InvalidScopeError, format_error(resp)
78
+ when 404 then
79
+ raise NotFoundError, format_error(resp)
80
+ when 422 then
81
+ raise ValidationError, format_error(resp)
82
+ when 429 then
83
+ raise RateLimitError, format_error(resp)
84
+ when 500 then
85
+ raise InternalServerError, format_error(resp)
86
+ when 503 then
87
+ raise ServiceUnavailableError, format_error(resp)
88
+ end
89
+ end
90
+
91
+ # API errors
92
+ if resp.body['status'] == 'fail'
93
+ raise Cryptoprocessing::APIError, resp.body['message']
94
+ end
95
+
96
+ if resp.status > 400
97
+ raise Cryptoprocessing::APIError, "[#{resp.status}] #{resp.body}"
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,37 @@
1
+ require 'cryptoprocessing/models/tracker'
2
+
3
+ module Cryptoprocessing
4
+ class Client
5
+ module Trackers
6
+ # Tracking address list
7
+ #
8
+ # @param [String] account_id
9
+ # @see https://api.cryptoprocessing.io/#bb7723d0-761b-46cd-f6ed-9ca2699f47df
10
+ def trackers(account_id, options = {})
11
+ out = nil
12
+ currency = if options[:currency] then options[:currency] else blockchain_type end
13
+ get("/v1/#{currency}/accounts/#{account_id}/tracing/address", options) do |resp|
14
+ out = resp.data['addresses'].map { |item| Cryptoprocessing::Tracker.new(self, item) }
15
+ yield(out, resp) if block_given?
16
+ end
17
+ out
18
+ end
19
+
20
+ # Add address for tracking
21
+ #
22
+ # @param [String] account_id
23
+ # @param [String] address
24
+ # @see https://api.cryptoprocessing.io/#bb7723d0-761b-46cd-f6ed-9ca2699f47df
25
+ def create_tracker(account_id, address, options = {})
26
+ out = nil
27
+ currency = if options[:currency] then options[:currency] else blockchain_type end
28
+ options[:address] = address
29
+ post("/v1/#{currency}/accounts/#{account_id}/tracing/address", options) do |resp|
30
+ out = Cryptoprocessing::Tracker.new(self, resp.data.merge(options))
31
+ yield(out, resp) if block_given?
32
+ end
33
+ out
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,90 @@
1
+ require 'cryptoprocessing/models/transaction'
2
+
3
+ module Cryptoprocessing
4
+ class Client
5
+ # @see https://api.cryptoprocessing.io/#c42e8a72-9e11-c074-22ef-4fc9a70a1a8f
6
+ module Transactions
7
+ TRANSACTION_SEND_TYPE = 'send'
8
+ TRANSACTION_SEND_TYPE_RAW = 'sendraw'
9
+
10
+ TRANSACTION_FEE_FASTEST = 'fastestFee'
11
+ TRANSACTION_FEE_HALF_HOUR = 'halfHourFee'
12
+ TRANSACTION_FEE_HOUR = 'hourFee'
13
+
14
+ # List transactions
15
+ #
16
+ # список транзакций
17
+ #
18
+ # @param [String] account_id
19
+ # @return [Array<Cryptoprocessing::Transaction>] A list of transactions
20
+ # @see https://api.cryptoprocessing.io/#690f04ca-cc2b-750b-17c6-4cc290a65d98
21
+ def transactions(account_id, options = {})
22
+ out = nil
23
+ currency = if options[:currency] then options[:currency] else blockchain_type end
24
+ get("/v1/#{currency}/accounts/#{account_id}/transactions", options) do |resp|
25
+ out = resp.data['transactions'].map { |item| Cryptoprocessing::Transaction.new(self, item) }
26
+ yield(out, resp) if block_given?
27
+ end
28
+ out
29
+ end
30
+
31
+ # List transactions filtered by address
32
+ #
33
+ # @param [String] account_id
34
+ # @param [String] address
35
+ # @return [Array<Cryptoprocessing::Transaction>] A list of transactions
36
+ # @see https://api.cryptoprocessing.io/#0e6e0dbc-1c1b-23db-dc54-a3b36ed276d8
37
+ def transactions_by_address(account_id, address, options = {})
38
+ out = nil
39
+ currency = if options[:currency] then options[:currency] else blockchain_type end
40
+ get("/v1/#{currency}/accounts/#{account_id}/transactions/address/#{address}", options) do |resp|
41
+ out = resp.data.map { |item| Cryptoprocessing::Transaction.new(self, item) }
42
+ yield(out, resp) if block_given?
43
+ end
44
+ out
45
+ end
46
+
47
+ # Send raw transaction signed transaction to the blockchain
48
+ #
49
+ # Отсылаем в блокчейн сырую подписанную транзакцию
50
+ #
51
+ # @param [String] raw_transaction_id
52
+ # @return [Cryptoprocessing::Transaction]
53
+ # @see https://api.cryptoprocessing.io/#655161a4-f6ff-6764-1667-8fb039912546
54
+ def send_raw_transaction(raw_transaction_id, options = {})
55
+ out = nil
56
+ currency = if options[:currency] then options[:currency] else blockchain_type end
57
+ options[:type] = TRANSACTION_SEND_TYPE_RAW
58
+ options[:raw_transaction_id] = raw_transaction_id
59
+ post("/v1/#{currency}/sendrawtx", options) do |resp|
60
+ out = Cryptoprocessing::Transaction.new(self, resp.data.merge(options))
61
+ yield(out, resp) if block_given?
62
+ end
63
+ out
64
+ end
65
+
66
+ # Create transaction
67
+ #
68
+ # Создаем транзакцию
69
+ #
70
+ # @param [String] account_id
71
+ # @return [Cryptoprocessing::Transaction]
72
+ # @see https://api.cryptoprocessing.io/#8dd94a75-4b09-588e-c9ad-c9cb5f165d72
73
+ def create_transaction(account_id, options = {})
74
+ out = nil
75
+ currency = if options[:currency] then options[:currency] else blockchain_type end
76
+ options[:type] = TRANSACTION_SEND_TYPE
77
+ options[:fee] = options[:fee] || TRANSACTION_FEE_FASTEST
78
+ options[:from_] = options[:from]
79
+ options[:to_] = options[:to]
80
+ options.delete(:from)
81
+ options.delete(:to)
82
+ post("/v1/#{currency}/accounts/#{account_id}/transactions", options) do |resp|
83
+ out = Cryptoprocessing::Transaction.new(self, resp.data.merge(options))
84
+ yield(out, resp) if block_given?
85
+ end
86
+ out
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,73 @@
1
+ module Cryptoprocessing
2
+
3
+ # Configuration options for {Client}, defaulting to values
4
+ # in {Default}
5
+ module Configurable
6
+ # @!attribute [w] access_token
7
+ # @return [String] Access token for authentication
8
+ attr_accessor :access_token, :blockchain_type, :user_agent
9
+ # @!attribute api_endpoint
10
+ # @return [String] Base URL for API requests.
11
+ attr_writer :email, :password, :api_endpoint, :api_namespace
12
+
13
+ class << self
14
+ # List of configurable keys for {Cryptoprocessing::Client}
15
+ # @return [Array] of option keys
16
+ def keys
17
+ @keys ||= [
18
+ :access_token,
19
+ :api_endpoint,
20
+ :api_namespace,
21
+ :blockchain_type,
22
+ :email,
23
+ :password,
24
+ :user_agent
25
+ ]
26
+ end
27
+ end
28
+
29
+ # Set configuration options using a block
30
+ def configure
31
+ yield self
32
+ end
33
+
34
+ # Reset configuration options to default values
35
+ def reset!
36
+ Cryptoprocessing::Configurable.keys.each do |key|
37
+ instance_variable_set(:"@#{key}", Cryptoprocessing::Default.options[key])
38
+ end
39
+ self
40
+ end
41
+ alias setup reset!
42
+
43
+ # Compares client options to a Hash of requested options
44
+ #
45
+ # @param opts [Hash] Options to compare with current client options
46
+ # @return [Boolean]
47
+ def same_options?(opts)
48
+ opts.hash == options.hash
49
+ end
50
+
51
+ def blockchain_type
52
+ @blockchain_type
53
+ end
54
+
55
+ def api_endpoint
56
+ File.join(@api_endpoint, '')
57
+ end
58
+
59
+ def api_namespace
60
+ File.join(@api_namespace, '')
61
+ end
62
+
63
+ def netrc?
64
+ !!@netrc
65
+ end
66
+
67
+ private
68
+
69
+ def options
70
+ Hash[Cryptoprocessing::Configurable.keys.map{|key| [key, instance_variable_get(:"@#{key}")]}]
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,140 @@
1
+ require 'net/http'
2
+ require 'json/ext'
3
+ require 'cryptoprocessing/version'
4
+ require 'cryptoprocessing/client/net_response'
5
+
6
+ module Cryptoprocessing
7
+ module Connection
8
+
9
+ def endpoint
10
+ api_endpoint
11
+ end
12
+
13
+ # @return [Net::HTTP]
14
+ def agent
15
+ base_uri = URI.parse(endpoint)
16
+ @agent = Net::HTTP.new(base_uri.host, base_uri.port)
17
+ @agent.use_ssl = true if base_uri.scheme == 'https'
18
+ # @agent.cert_store = self.class.whitelisted_certificates
19
+ @agent.ssl_version = :TLSv1
20
+ @agent
21
+ end
22
+
23
+ ##
24
+ # @param [String] method
25
+ # @param [String] path
26
+ # @param [String] body
27
+ # @param [String] headers
28
+ def request(method, path, body = nil, headers = {})
29
+ # Prepend configured namespace
30
+ path = "#{@api_namespace}#{path}"
31
+
32
+ case method
33
+ when 'GET' then
34
+ req = Net::HTTP::Get.new(path)
35
+ when 'PUT' then
36
+ req = Net::HTTP::Put.new(path)
37
+ when 'POST' then
38
+ req = Net::HTTP::Post.new(path)
39
+ when 'DELETE' then
40
+ req = Net::HTTP::Delete.new(path)
41
+ else
42
+ raise
43
+ end
44
+
45
+ req.body = body
46
+
47
+ # All requests with JSON encoded body
48
+ req['Content-Type'] = 'application/json'
49
+
50
+ # Set User Agent to Gem name and version
51
+ req['User-Agent'] = user_agent
52
+
53
+ auth_headers(method, path, body).each do |key, val|
54
+ req[key] = val
55
+ end
56
+ headers.each do |key, val|
57
+ req[key] = val
58
+ end
59
+
60
+ resp = agent.request(req)
61
+ out = Cryptoprocessing::NetHTTPResponse.new(resp)
62
+ Cryptoprocessing::check_response_status(out)
63
+ yield(out) if block_given?
64
+ out.data
65
+ end
66
+
67
+ def auth_headers(method, path, body)
68
+ {:Authorization => "Bearer #{@access_token}"}
69
+ end
70
+
71
+ def reset_agent
72
+ @agent = nil
73
+ end
74
+
75
+ ##
76
+ # HTTP GET method
77
+ #
78
+ # @param [String] path
79
+ def get(path, params = {})
80
+ uri = path
81
+ if params.count > 0
82
+ uri += "?#{URI.encode_www_form(params)}"
83
+ end
84
+
85
+ headers = {}
86
+
87
+ request('GET', uri, nil, headers) do |resp|
88
+ if params[:fetch_all] == true &&
89
+ resp.body.has_key?('pagination') &&
90
+ resp.body['pagination']['next_uri'] != nil
91
+ params[:starting_after] = resp.body['data'].last['id']
92
+ get(path, params) do |page|
93
+ body = resp.body
94
+ body['data'] += page.data
95
+ resp.body = body
96
+ yield(resp) if block_given?
97
+ end
98
+ else
99
+ yield(resp) if block_given?
100
+ end
101
+ end
102
+ end
103
+
104
+ ##
105
+ # HTTP PUT method
106
+ #
107
+ # @param [String] path
108
+ def put(path, params)
109
+ headers = {}
110
+
111
+ request('PUT', path, params.to_json, headers) do |resp|
112
+ yield(resp) if block_given?
113
+ end
114
+ end
115
+
116
+ ##
117
+ # HTTP POST method
118
+ #
119
+ # @param [String] path
120
+ def post(path, params)
121
+ headers = {}
122
+
123
+ request('POST', path, params.to_json, headers) do |resp|
124
+ yield(resp) if block_given?
125
+ end
126
+ end
127
+
128
+ ##
129
+ # HTTP DELETE method
130
+ #
131
+ # @param [String] path
132
+ def delete(path, params)
133
+ headers = {}
134
+
135
+ request('DELETE', path, nil, headers) do |resp|
136
+ yield(resp) if block_given?
137
+ end
138
+ end
139
+ end
140
+ end