diff --git a/lib/straight/address_providers/base.rb b/lib/straight/address_providers/base.rb index 52efd80..4d037bb 100644 --- a/lib/straight/address_providers/base.rb +++ b/lib/straight/address_providers/base.rb @@ -23,6 +23,12 @@ def new_address(keychain_id:, **args) def takes_fees? false end + + # Address provider is expected to define SUPPORTED_CURRENCIES as an + # Enumerable with valid currency codes. e.g. 'EUR', 'USD' + def currency_supported?(currency) + SUPPORTED_CURRENCIES.include?(currency) + end end end end diff --git a/lib/straight/exchange_rate_adapters/fiat_adapters/fixer_adapter.rb b/lib/straight/exchange_rate_adapters/fiat_adapters/fixer_adapter.rb index dd859b0..8e7eb0c 100644 --- a/lib/straight/exchange_rate_adapters/fiat_adapters/fixer_adapter.rb +++ b/lib/straight/exchange_rate_adapters/fiat_adapters/fixer_adapter.rb @@ -4,8 +4,8 @@ class FixerAdapter < FiatAdapter FETCH_URL = "http://api.fixer.io/latest?base=#{CROSS_RATE_CURRENCY}" def rate_for(currency_code) - super - rate = get_rate_value_from_hash(@rates, 'rates', currency_code) + rate = super + rate ||= get_rate_value_from_hash(@rates, 'rates', currency_code) rate_to_f(rate) end end diff --git a/lib/straight/gateway.rb b/lib/straight/gateway.rb index 24fdbd5..9c99503 100644 --- a/lib/straight/gateway.rb +++ b/lib/straight/gateway.rb @@ -91,6 +91,15 @@ def new_order(args) raise OrderAmountInvalid, "amount cannot be nil and should be more than 0" end # Setting default values + + if address_provider.takes_fees? && + !address_provider.currency_supported?(args[:currency]) + supported_currency = select_supported_currency_by_address_provider + args[:amount] = convert_amount_to_supported_currency(args[:amount], + args[:currency], supported_currency) + args[:currency] = supported_currency + end + args[:currency] ||= default_currency args[:btc_denomination] ||= :satoshi @@ -197,6 +206,18 @@ def address_provider_type private + def select_supported_currency_by_address_provider + address_provider.class::SUPPORTED_CURRENCIES.first + end + + def convert_amount_to_supported_currency(amount, currency, supported_currency) + adapter = ExchangeRate::FixerAdapter.instance + rate_for_supported_currency = adapter.rate_for(supported_currency) + rate_for_currency = adapter.rate_for(currency) + + (amount * rate_for_supported_currency) / rate_for_currency + end + # Calls the block with each adapter until one of them does not fail. # Fails with the: # - priority_exception, if it is set and was raised at least once diff --git a/spec/lib/exchange_rate_adapters/fiat_adapters/fixer_adapter_spec.rb b/spec/lib/exchange_rate_adapters/fiat_adapters/fixer_adapter_spec.rb index 270fbb8..bb5b372 100644 --- a/spec/lib/exchange_rate_adapters/fiat_adapters/fixer_adapter_spec.rb +++ b/spec/lib/exchange_rate_adapters/fiat_adapters/fixer_adapter_spec.rb @@ -19,4 +19,8 @@ expect( -> { @exchange_adapter.rate_for('KZT') }).to raise_error(Straight::ExchangeRate::Adapter::CurrencyNotSupported) end + it "returns 1.0 when the currency is the FiatAdapter::CROSS_RATE_CURRENCY" do + expect(@exchange_adapter. + rate_for(Straight::ExchangeRate::FiatAdapter::CROSS_RATE_CURRENCY)).to eq(1.0) + end end diff --git a/spec/lib/gateway_spec.rb b/spec/lib/gateway_spec.rb index 49d81d1..85e1086 100644 --- a/spec/lib/gateway_spec.rb +++ b/spec/lib/gateway_spec.rb @@ -74,6 +74,18 @@ @gateway.order_status_changed(order) end + describe "when the address provider doesn't support the selected currency" do + it "converts the currency to one the address provider supports" do + @gateway.address_provider = AddressProvider.new(provider: :cashila) + allow(@gateway.address_provider).to receive(:new_address_and_amount) + allow(@gateway).to receive(:select_supported_currency_by_address_provider). + and_return("EUR") + expect(@gateway).to receive(:amount_from_exchange_rate). + with(0.91996, currency: "EUR", btc_denomination: :satoshi) + @gateway.new_order(amount: 1, keychain_id: 1, currency: "USD") + end + end + describe "exchange rate calculation" do it "sets order amount in satoshis calculated from another currency" do @@ -153,3 +165,13 @@ end end + +AddressProvider = Struct.new(:provider) do + def takes_fees? + true + end + + def currency_supported?(currency) + currency == "EUR" + end +end