class CoinSync::Importers::KrakenAPI

Constants

API_RENEWAL_INTERVAL
BASE_URL

Public Class Methods

new(config, params = {}) click to toggle source
Calls superclass method CoinSync::Importers::Base::new
# File lib/coinsync/importers/kraken_api.rb, line 24
def initialize(config, params = {})
  super
  @api_key = params['api_key']
  @secret_api_key = params['private_key']
  @decoded_secret = Base64.decode64(@secret_api_key) if @secret_api_key
end

Public Instance Methods

can_import?(type) click to toggle source
# File lib/coinsync/importers/kraken_api.rb, line 31
def can_import?(type)
  @api_key && @secret_api_key && [:balances, :transactions].include?(type)
end
import_balances() click to toggle source
# File lib/coinsync/importers/kraken_api.rb, line 81
def import_balances
  response = make_request('/0/private/Balance')

  case response
  when Net::HTTPSuccess
    json = JSON.parse(response.body)

    if !json['error'].empty? || !json['result']
      raise "Kraken importer: Invalid response: #{response.body}"
    end

    return json['result'].map { |k, v|
      [Kraken::LedgerEntry.parse_currency(k), BigDecimal.new(v)]
    }.select { |currency, amount|
      amount > 0 && currency.crypto?
    }.map { |currency, amount|
      Balance.new(currency, available: amount)
    }
  when Net::HTTPBadRequest
    raise "Kraken importer: Bad request: #{response.body}"
  else
    raise "Kraken importer: Bad response: #{response.body}"
  end
end
import_transactions(filename) click to toggle source
# File lib/coinsync/importers/kraken_api.rb, line 35
def import_transactions(filename)
  offset = 0
  entries = []
  slowdown = false

  loop do
    response = make_request('/0/private/Ledgers', ofs: offset)
    print slowdown ? '-' : '.'
    sleep(2 * API_RENEWAL_INTERVAL) if slowdown   # rate limiting

    case response
    when Net::HTTPSuccess
      json = JSON.parse(response.body)

      if json['result'].nil? || json['error'].length > 0
        if json['error'].first == 'EAPI:Rate limit exceeded'
          slowdown = true
          print '!'
          sleep(4 * API_RENEWAL_INTERVAL)
          next
        else
          raise "Kraken importer: Invalid response: #{response.body}"
        end
      end

      data = json['result']
      list = data && data['ledger']

      if !list
        raise "Kraken importer: No data returned: #{response.body}"
      end

      break if list.empty?

      entries.concat(list.values)
      offset += list.length
    when Net::HTTPBadRequest
      raise "Kraken importer: Bad request: #{response.body}"
    else
      raise "Kraken importer: Bad response: #{response.body}"
    end
  end

  File.write(filename, JSON.pretty_generate(entries) + "\n")
end
read_transaction_list(source) click to toggle source
# File lib/coinsync/importers/kraken_api.rb, line 106
def read_transaction_list(source)
  json = JSON.parse(source.read)

  build_transaction_list(json.map { |hash| Kraken::LedgerEntry.from_json(hash) })
end

Private Instance Methods

make_request(path, params = {}) click to toggle source
# File lib/coinsync/importers/kraken_api.rb, line 114
def make_request(path, params = {})
  (@api_key && @secret_api_key) or raise "Public and secret API keys must be provided"

  nonce = (Time.now.to_f * 1000).to_i

  url = URI(BASE_URL + path)
  params['nonce'] = nonce

  post_data = URI.encode_www_form(params)
  string_to_hash = path + OpenSSL::Digest.new('sha256', nonce.to_s + post_data).digest
  hmac = Base64.strict_encode64(OpenSSL::HMAC.digest('sha512', @decoded_secret, string_to_hash))

  Request.post(url) do |request|
    request.body = post_data
    request['API-Key'] = @api_key
    request['API-Sign'] = hmac
  end
end