class Danconia::Exchange

Public Instance Methods

rate(from, to, **opts) click to toggle source
# File lib/danconia/exchange.rb, line 5
def rate from, to, **opts
  return 1.0 if from == to

  pair = Pair.new(from, to)
  rates = direct_and_inverted_rates(opts)
  rates[pair] or indirect_rate(pair, rates) or raise Errors::ExchangeRateNotFound.new(from, to)
end
rates(**_opts) click to toggle source

Override this method in subclasses. Should return a map of pairs to rates. See `FixedRates` for an example implementation.

# File lib/danconia/exchange.rb, line 15
def rates **_opts
  raise NotImplementedError
end

Private Instance Methods

array_of_rates_to_hash(array) click to toggle source
# File lib/danconia/exchange.rb, line 38
def array_of_rates_to_hash array
  pairs = array.map { |er| er[:pair] }
  if pairs.size != pairs.uniq.size
    raise ArgumentError, "Exchange returned duplicate pairs. Maybe you forgot a filter?\n#{array}"
  end

  Hash[array.map { |er| er.values_at(:pair, :rate) }]
end
direct_and_inverted_rates(opts) click to toggle source

Returns the original rates plus the inverted ones, to simplify rate finding logic. Also wraps the pair strings into Pair objects.

# File lib/danconia/exchange.rb, line 23
def direct_and_inverted_rates opts
  rates(opts).each_with_object({}) do |(pair_str, rate), rs|
    pair = Pair.parse(pair_str)
    rs[pair] = rate
    rs[pair.invert] ||= 1.0 / rate
  end
end
indirect_rate(ind_pair, rates) click to toggle source
# File lib/danconia/exchange.rb, line 31
def indirect_rate ind_pair, rates
  if (from_pair = rates.keys.detect { |pair| pair.from == ind_pair.from }) &&
     (to_pair = rates.keys.detect { |pair| pair.to == ind_pair.to })
    rates[from_pair] * rates[to_pair]
  end
end