lib/chainalysis/client.rb in chainalysis-0.1.0 vs lib/chainalysis/client.rb in chainalysis-0.2.0

- old
+ new

@@ -9,24 +9,189 @@ class BadRequestError < Error; end class NotFoundError < Error; end class RateLimitError < Error; end class ApiError < Error; end - class Client + # Base client class handling common functionality + class BaseClient BASE_URL = 'https://api.chainalysis.com/api/kyt' ADMIN_URL = 'https://api.chainalysis.com/admin' - VERSION = '0.1.0' + VERSION = '0.2.0' attr_reader :api_key, :adapter def initialize(api_key:, adapter: Faraday.default_adapter, stubs: nil) @api_key = api_key @adapter = adapter @stubs = stubs end - # Transfer Registration + protected + + def client + @client ||= Faraday.new(url: BASE_URL) do |conn| + conn.headers['Token'] = api_key + conn.headers['Accept'] = 'application/json' + conn.headers['Content-Type'] = 'application/json' + conn.adapter adapter, @stubs + end + end + + def admin_client + @admin_client ||= Faraday.new(url: ADMIN_URL) do |conn| + conn.headers['Token'] = api_key + conn.headers['Accept'] = 'application/json' + conn.headers['Content-Type'] = 'application/json' + conn.adapter adapter, @stubs + end + end + + def handle_response(response) + case response.status + when 200, 201, 202 + return {} if response.body.empty? + + JSON.parse(response.body) + when 400 + raise BadRequestError, error_message(response) + when 403 + raise AuthenticationError, error_message(response) + when 404 + raise NotFoundError, error_message(response) + when 429 + raise RateLimitError, error_message(response) + else + raise ApiError, error_message(response) + end + end + + def error_message(response) + return response.body if response.body.empty? + + error = JSON.parse(response.body) + error['message'] || error['error'] || response.body + rescue JSON::ParserError + response.body + end + + def get_request(url, params = {}, admin: false) + client = admin ? admin_client : self.client + response = client.get(url) do |req| + req.params = params if params + end + handle_response(response) + end + + def post_request(url, body = {}) + response = client.post(url) do |req| + req.body = JSON.generate(body) unless body.empty? + end + handle_response(response) + end + + def delete_request(url) + response = client.delete(url) + handle_response(response) + end + end + + # Client for V1 API endpoints + class V1Client < BaseClient + # Transfer endpoints + def register_received_transfer(user_id:, transfers:) + post_request("v1/users/#{user_id}/transfers/received", transfers) + end + + def get_received_transfers(user_id:, limit: nil, offset: nil) + params = {} + params[:limit] = limit if limit + params[:offset] = offset if offset + get_request("v1/users/#{user_id}/transfers/received", params) + end + + def register_sent_transfer(user_id:, transfers:) + post_request("v1/users/#{user_id}/transfers/sent", transfers) + end + + def get_sent_transfers(user_id:, limit: nil, offset: nil) + params = {} + params[:limit] = limit if limit + params[:offset] = offset if offset + get_request("v1/users/#{user_id}/transfers/sent", params) + end + + # Withdrawal address endpoints + def register_withdrawal_addresses(user_id:, addresses:) + post_request("v1/users/#{user_id}/withdrawaladdresses", addresses) + end + + def get_withdrawal_addresses(user_id:, limit: nil, offset: nil) + params = {} + params[:limit] = limit if limit + params[:offset] = offset if offset + get_request("v1/users/#{user_id}/withdrawaladdresses", params) + end + + def delete_withdrawal_address(user_id:, asset:, address:) + delete_request("v1/users/#{user_id}/withdrawaladdresses/#{asset}/#{address}") + end + + # Deposit address endpoints + def register_deposit_addresses(user_id:, addresses:) + post_request("v1/users/#{user_id}/depositaddresses", addresses) + end + + def get_deposit_addresses(user_id:, limit: nil, offset: nil) + params = {} + params[:limit] = limit if limit + params[:offset] = offset if offset + get_request("v1/users/#{user_id}/depositaddresses", params) + end + + def delete_deposit_address(user_id:, asset:, address:) + delete_request("v1/users/#{user_id}/depositaddresses/#{asset}/#{address}") + end + + # Alert endpoints + def get_alerts(params = {}) + get_request('v1/alerts/', params) + end + + def assign_alert(alert_identifier:, alert_assignee:) + post_request("v1/alerts/#{alert_identifier}/assignment", + { alertAssignee: alert_assignee }) + end + + def update_alert_status(alert_identifier:, status:, comment: nil) + body = { status: status } + body[:comment] = comment if comment + post_request("v1/alerts/#{alert_identifier}/statuses", body) + end + + def get_alert_activity(alert_identifier:) + get_request("v1/alerts/#{alert_identifier}/activity") + end + + # User endpoints + def get_users(limit: nil, offset: nil) + params = {} + params[:limit] = limit if limit + params[:offset] = offset if offset + get_request('v1/users/', params) + end + + def get_user(user_id:) + get_request("v1/users/#{user_id}") + end + + def rename_users(renames:) + post_request('v1/users/rename', renames) + end + end + + # Client for V2 API endpoints + class V2Client < BaseClient def register_transfer(user_id:, network:, asset:, transfer_reference:, direction:, **options) post_request( "v2/users/#{user_id}/transfers", { network: network, @@ -36,13 +201,12 @@ **options } ) end - # Withdrawal Attempt Registration - def register_withdrawal_attempt(user_id:, network:, asset:, address:, attempt_identifier:, asset_amount:, - attempt_timestamp:, **options) + def register_withdrawal_attempt(user_id:, network:, asset:, address:, attempt_identifier:, + asset_amount:, attempt_timestamp:, **options) post_request( "v2/users/#{user_id}/withdrawal-attempts", { network: network, asset: asset, @@ -53,11 +217,10 @@ **options } ) end - # Transfer Endpoints def get_transfer(external_id:, format_type: nil) params = { format_type: format_type } if format_type get_request("v2/transfers/#{external_id}", params) end @@ -71,11 +234,10 @@ def get_transfer_network_identifications(external_id:) get_request("v2/transfers/#{external_id}/network-identifications") end - # Withdrawal Attempt Endpoints def get_withdrawal_attempt(external_id:, format_type: nil) params = { format_type: format_type } if format_type get_request("v2/withdrawal-attempts/#{external_id}", params) end @@ -93,81 +255,25 @@ def get_withdrawal_attempt_network_identifications(external_id:) get_request("v2/withdrawal-attempts/#{external_id}/network-identifications") end - # Categories def get_categories get_request('v2/categories') end - # Administration def get_internal_users get_request('organization/users', admin: true) end + end - private - - def client - @client ||= Faraday.new(url: BASE_URL) do |conn| - conn.headers['Token'] = api_key - conn.headers['Accept'] = 'application/json' - conn.headers['Content-Type'] = 'application/json' - - conn.adapter adapter, @stubs - end + # Main client class that provides access to both V1 and V2 clients + class Client < BaseClient + def v1 + @v1 ||= V1Client.new(api_key: api_key, adapter: adapter, stubs: @stubs) end - def admin_client - @admin_client ||= Faraday.new(url: ADMIN_URL) do |conn| - conn.headers['Token'] = api_key - conn.headers['Accept'] = 'application/json' - conn.headers['Content-Type'] = 'application/json' - - conn.adapter adapter, @stubs - end - end - - def handle_response(response) - case response.status - when 200, 201, 202 - return {} if response.body.empty? - - JSON.parse(response.body) - when 400 - raise BadRequestError, error_message(response) - when 403 - raise AuthenticationError, error_message(response) - when 404 - raise NotFoundError, error_message(response) - when 429 - raise RateLimitError, error_message(response) - else - raise ApiError, error_message(response) - end - end - - def error_message(response) - return response.body if response.body.empty? - - error = JSON.parse(response.body) - error['message'] || error['error'] || response.body - rescue JSON::ParserError - response.body - end - - def get_request(url, params = {}, admin: false) - client = admin ? admin_client : self.client - response = client.get(url) do |req| - req.params = params if params - end - handle_response(response) - end - - def post_request(url, body = {}) - response = client.post(url) do |req| - req.body = JSON.generate(body) unless body.empty? - end - handle_response(response) + def v2 + @v2 ||= V2Client.new(api_key: api_key, adapter: adapter, stubs: @stubs) end end end