module Straight::GatewayModule::Includable

Public Instance Methods

address_provider_type() click to toggle source
# File lib/straight/gateway.rb, line 177
def address_provider_type
  @address_provider ? @address_provider.class.name.split('::')[-1].to_sym  : :Bip32
end
amount_from_exchange_rate(amount, currency:, btc_denomination: :satoshi) click to toggle source

Gets exchange rates from one of the exchange rate adapters, then calculates how much BTC does the amount in the given currency represents.

You can also feed this method various bitcoin denominations. It will always return amount in Satoshis.

# File lib/straight/gateway.rb, line 149
def amount_from_exchange_rate(amount, currency:, btc_denomination: :satoshi)
  currency         = self.default_currency if currency.nil?
  btc_denomination = :satoshi              if btc_denomination.nil?
  currency = currency.to_s.upcase
  if currency == 'BTC'
    return Satoshi.new(amount, from_unit: btc_denomination).to_i
  end

  try_adapters(@exchange_rate_adapters, type: "exchange rate") do |a|
    a.convert_from_currency(amount, currency: currency)
  end
end
blockchain_adapters() click to toggle source
# File lib/straight/gateway.rb, line 73
def blockchain_adapters
  return test_blockchain_adapters if test_mode
  @blockchain_adapters
end
current_exchange_rate(currency=self.default_currency) click to toggle source
# File lib/straight/gateway.rb, line 162
def current_exchange_rate(currency=self.default_currency)
  currency = currency.to_s.upcase
  try_adapters(@exchange_rate_adapters, type: "exchange rate") do |a|
    a.rate_for(currency)
  end
end
fetch_balance_for(address) click to toggle source
# File lib/straight/gateway.rb, line 127
def fetch_balance_for(address)
  try_adapters(blockchain_adapters, type: "blockchain") { |b| b.fetch_balance_for(address) }
end
fetch_transaction(tid, address: nil) click to toggle source
# File lib/straight/gateway.rb, line 119
def fetch_transaction(tid, address: nil)
  try_adapters(blockchain_adapters, type: "blockchain") { |b| b.fetch_transaction(tid, address: address) }
end
fetch_transactions_for(address) click to toggle source
# File lib/straight/gateway.rb, line 123
def fetch_transactions_for(address)
  try_adapters(blockchain_adapters, type: "blockchain", raise_exceptions: [Blockchain::Adapter::BitcoinAddressInvalid]) { |b| b.fetch_transactions_for(address) }
end
keychain() click to toggle source
# File lib/straight/gateway.rb, line 131
def keychain
  key = self.test_mode ? self.test_pubkey : self.pubkey
  @keychain ||= BTC::Keychain.new(xpub: key)
end
new_order(amount:, keychain_id: nil, currency: nil, btc_denomination: :satoshi) click to toggle source

Creates a new order for the address derived from the pubkey and the keychain_id argument provided. See explanation of this keychain_id argument is in the description for the AddressProvider::Base#new_address method.

# File lib/straight/gateway.rb, line 84
def new_order(args)

  # Args: amount:, keychain_id: nil, currency: nil, btc_denomination: :satoshi
  #
  # The reason these arguments are supplied as a hash and not as named arguments
  # is because we don't know in advance which arguments are required for a particular
  # AddressAdapter. So we accpet all, check manually for required ones like :amount,
  # set default values where needed and then hand them all to address_adapter.
  if args[:amount].nil? || !args[:amount].kind_of?(Numeric) || args[:amount] <= 0
    raise OrderAmountInvalid, "amount cannot be nil and should be more than 0" 
  end
  # Setting default values
  args[:currency]         ||= default_currency
  args[:btc_denomination] ||= :satoshi

  amount = args[:amount_from_exchange_rate] = amount_from_exchange_rate(
    args[:amount],
    currency:         args[:currency],
    btc_denomination: args[:btc_denomination]
  )

  if address_provider.takes_fees?
    address, amount = address_provider.new_address_and_amount(**args)
  else
    address = address_provider.new_address(**args)
  end

  order             = Kernel.const_get(order_class).new
  order.gateway     = self
  order.keychain_id = args[:keychain_id]
  order.address     = address
  order.amount      = amount
  order
end
order_status_changed(order) click to toggle source

This is a callback method called from each order whenever an order status changes.

# File lib/straight/gateway.rb, line 138
def order_status_changed(order)
  @order_callbacks.each do |c|
    c.call(order)
  end
end
pubkey_missing?() click to toggle source
# File lib/straight/gateway.rb, line 173
def pubkey_missing?
  address_provider_type == :Bip32 && !test_mode && pubkey.to_s.empty?
end
test_blockchain_adapters() click to toggle source
# File lib/straight/gateway.rb, line 78
def test_blockchain_adapters
  @blockchain_adapters.map{ |el| el.class.testnet_adapter rescue next }.compact
end
test_pubkey_missing?() click to toggle source
# File lib/straight/gateway.rb, line 169
def test_pubkey_missing?
  address_provider_type == :Bip32 && test_mode && test_pubkey.to_s.empty?
end

Private Instance Methods

try_adapters(adapters, type: nil, raise_exceptions: []) { |adapter| ... } click to toggle source

Calls the block with each adapter until one of them does not fail. Fails with the last exception.

# File lib/straight/gateway.rb, line 185
def try_adapters(adapters, type: nil, raise_exceptions: [], &block)

  # TODO: specify which adapters are unavailable (blockchain or exchange rate)
  raise NoAdaptersAvailable, "the list of #{type} adapters is empty or nil" if adapters.nil? || adapters.empty?

  last_exception = nil
  adapters.each do |adapter|
    begin
      result = yield(adapter)
      last_exception = nil
      return result
    rescue => e
      raise e if raise_exceptions.include?(e)
      last_exception = e
      # If an Exception is raised, it passes on
      # to the next adapter and attempts to call a method on it.
    end
  end
  raise last_exception if last_exception
end