Class: Honeymaker::Clients::Coinbase

Inherits:
Honeymaker::Client show all
Defined in:
lib/honeymaker/clients/coinbase.rb

Constant Summary collapse

URL =
"https://api.coinbase.com"
RATE_LIMITS =
{ default: 100, orders: 100 }.freeze

Constants inherited from Honeymaker::Client

Honeymaker::Client::OPTIONS

Instance Attribute Summary

Attributes inherited from Honeymaker::Client

#api_key, #api_secret

Instance Method Summary collapse

Methods inherited from Honeymaker::Client

rate_limits, #validate

Constructor Details

#initialize(api_key: nil, api_secret: nil, proxy: nil, logger: nil) ⇒ Coinbase

Returns a new instance of Coinbase.



11
12
13
14
# File 'lib/honeymaker/clients/coinbase.rb', line 11

def initialize(api_key: nil, api_secret: nil, proxy: nil, logger: nil)
  super
  @api_secret = @api_secret&.gsub('\n', "\n")
end

Instance Method Details

#cancel_orders(order_ids:) ⇒ Object



64
65
66
# File 'lib/honeymaker/clients/coinbase.rb', line 64

def cancel_orders(order_ids:)
  post("/api/v3/brokerage/orders/batch_cancel", { order_ids: order_ids })
end

#create_order(client_order_id:, product_id:, side:, order_configuration:) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/honeymaker/clients/coinbase.rb', line 47

def create_order(client_order_id:, product_id:, side:, order_configuration:)
  result = post("/api/v3/brokerage/orders", {
    client_order_id: client_order_id, product_id: product_id,
    side: side, order_configuration: order_configuration
  })
  return result if result.failure?

  raw = result.data
  if raw["success"] == false
    error_msg = raw.dig("error_response", "message") || "Order creation failed"
    return Result::Failure.new(error_msg)
  end

  order_id = raw.dig("success_response", "order_id")
  Result::Success.new({ order_id: order_id, raw: raw })
end

#get_api_key_permissionsObject



104
105
106
# File 'lib/honeymaker/clients/coinbase.rb', line 104

def get_api_key_permissions
  get("/api/v3/brokerage/key_permissions")
end

#get_balances(portfolio_uuid: nil) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/honeymaker/clients/coinbase.rb', line 116

def get_balances(portfolio_uuid: nil)
  unless portfolio_uuid
    portfolios_result = list_portfolios
    return portfolios_result if portfolios_result.failure?

    portfolio = Array(portfolios_result.data["portfolios"]).first
    return Result::Failure.new("No portfolios found") unless portfolio
    portfolio_uuid = portfolio["uuid"]
  end

  result = get_portfolio_breakdown(portfolio_uuid: portfolio_uuid)
  return result if result.failure?

  balances = {}
  positions = result.data.dig("breakdown", "spot_positions") || []
  positions.each do |position|
    symbol = position["asset"]
    next unless symbol

    free = BigDecimal((position["available_to_trade_crypto"] || "0").to_s)
    total = BigDecimal((position["total_balance_crypto"] || "0").to_s)
    locked = total - free
    next if free.zero? && locked.zero?
    balances[symbol] = { free: free, locked: locked }
  end

  Result::Success.new(balances)
end

#get_order(order_id:) ⇒ Object



16
17
18
19
20
21
22
# File 'lib/honeymaker/clients/coinbase.rb', line 16

def get_order(order_id:)
  result = get("/api/v3/brokerage/orders/historical/#{order_id}")
  return result if result.failure?

  raw = result.data.is_a?(Hash) && result.data.key?("order") ? result.data["order"] : result.data
  Result::Success.new(normalize_order(order_id, raw))
end

#get_portfolio_breakdown(portfolio_uuid:, currency: nil) ⇒ Object



145
146
147
# File 'lib/honeymaker/clients/coinbase.rb', line 145

def get_portfolio_breakdown(portfolio_uuid:, currency: nil)
  get("/api/v3/brokerage/portfolios/#{portfolio_uuid}", { currency: currency })
end

#get_public_product(product_id:, get_tradability_status: nil) ⇒ Object



79
80
81
# File 'lib/honeymaker/clients/coinbase.rb', line 79

def get_public_product(product_id:, get_tradability_status: nil)
  get("/api/v3/brokerage/market/products/#{product_id}", { get_tradability_status: get_tradability_status })
end

#get_public_product_book(product_id:, limit: nil, aggregation_price_increment: nil) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/honeymaker/clients/coinbase.rb', line 83

def get_public_product_book(product_id:, limit: nil, aggregation_price_increment: nil)
  with_rescue do
    response = connection.get do |req|
      req.url "/api/v3/brokerage/market/product_book"
      req.headers = auth_headers(req)
      req.params = {
        product_id: product_id, limit: limit,
        aggregation_price_increment: aggregation_price_increment
      }.compact
      req.options.params_encoder = Faraday::FlatParamsEncoder
    end
    response.body
  end
end

#get_public_product_candles(product_id:, start_time:, end_time:, granularity:, limit: nil) ⇒ Object



98
99
100
101
102
# File 'lib/honeymaker/clients/coinbase.rb', line 98

def get_public_product_candles(product_id:, start_time:, end_time:, granularity:, limit: nil)
  get("/api/v3/brokerage/market/products/#{product_id}/candles", {
    start: start_time, end: end_time, granularity: granularity, limit: limit
  })
end

#list_accountsObject



108
109
110
# File 'lib/honeymaker/clients/coinbase.rb', line 108

def list_accounts
  get("/api/v3/brokerage/accounts")
end

#list_fills(product_id: nil, order_id: nil, start_sequence_timestamp: nil, end_sequence_timestamp: nil, limit: nil, cursor: nil) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/honeymaker/clients/coinbase.rb', line 155

def list_fills(product_id: nil, order_id: nil, start_sequence_timestamp: nil,
               end_sequence_timestamp: nil, limit: nil, cursor: nil)
  with_rescue do
    response = connection.get do |req|
      req.url "/api/v3/brokerage/orders/historical/fills"
      req.headers = auth_headers(req)
      req.params = {
        product_id: product_id, order_id: order_id,
        start_sequence_timestamp: start_sequence_timestamp,
        end_sequence_timestamp: end_sequence_timestamp,
        limit: limit, cursor: cursor
      }.compact
      req.options.params_encoder = Faraday::FlatParamsEncoder
    end
    response.body
  end
end

#list_orders(order_ids: nil, product_ids: nil, product_type: nil, order_status: nil, time_in_forces: nil, order_types: nil, order_side: nil, start_date: nil, end_date: nil, order_placement_source: nil, contract_expiry_type: nil, asset_filters: nil, limit: nil, cursor: nil, sort_by: nil) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/honeymaker/clients/coinbase.rb', line 24

def list_orders(order_ids: nil, product_ids: nil, product_type: nil, order_status: nil,
                time_in_forces: nil, order_types: nil, order_side: nil, start_date: nil,
                end_date: nil, order_placement_source: nil, contract_expiry_type: nil,
                asset_filters: nil, limit: nil, cursor: nil, sort_by: nil)
  with_rescue do
    response = connection.get do |req|
      req.url "/api/v3/brokerage/orders/historical/batch"
      req.headers = auth_headers(req)
      req.params = {
        order_ids: order_ids, product_ids: product_ids, product_type: product_type,
        order_status: order_status, time_in_forces: time_in_forces,
        order_types: order_types, order_side: order_side,
        start_date: start_date, end_date: end_date,
        order_placement_source: order_placement_source,
        contract_expiry_type: contract_expiry_type,
        asset_filters: asset_filters, limit: limit, cursor: cursor, sort_by: sort_by
      }.compact
      req.options.params_encoder = Faraday::FlatParamsEncoder
    end
    response.body
  end
end

#list_portfoliosObject



112
113
114
# File 'lib/honeymaker/clients/coinbase.rb', line 112

def list_portfolios
  get("/api/v3/brokerage/portfolios")
end

#list_public_products(limit: nil, offset: nil, product_type: nil, product_ids: nil, contract_expiry_type: nil, expiring_contract_status: nil, get_tradability_status: nil, get_all_products: nil) ⇒ Object



68
69
70
71
72
73
74
75
76
77
# File 'lib/honeymaker/clients/coinbase.rb', line 68

def list_public_products(limit: nil, offset: nil, product_type: nil, product_ids: nil,
                         contract_expiry_type: nil, expiring_contract_status: nil,
                         get_tradability_status: nil, get_all_products: nil)
  get("/api/v3/brokerage/market/products", {
    limit: limit, offset: offset, product_type: product_type, product_ids: product_ids,
    contract_expiry_type: contract_expiry_type,
    expiring_contract_status: expiring_contract_status,
    get_tradability_status: get_tradability_status, get_all_products: get_all_products
  })
end

#list_transactions(account_id:, limit: nil, starting_after: nil) ⇒ Object



173
174
175
# File 'lib/honeymaker/clients/coinbase.rb', line 173

def list_transactions(account_id:, limit: nil, starting_after: nil)
  get("/v2/accounts/#{}/transactions", { limit: limit, starting_after: starting_after })
end

#send_money(account_id:, to:, amount:, currency:, idem: nil) ⇒ Object



149
150
151
152
153
# File 'lib/honeymaker/clients/coinbase.rb', line 149

def send_money(account_id:, to:, amount:, currency:, idem: nil)
  post("/v2/accounts/#{}/transactions", {
    type: "send", to: to, amount: amount, currency: currency, idem: idem
  })
end