mirror of
https://github.com/we-promise/sure.git
synced 2026-05-07 12:54:04 +00:00
* [FEATURE] Add CoinStats exchange portfolios and normalize linked investment charts * [BUGFIX] Fix CoinStats PR regressions * [BUGFIX] Fix CoinStats PR review findings * [BUGFIX] Address follow-up CoinStats PR feedback * [REFACTO] Extract CoinStats exchange account helpers * [BUGFIX] Batch linked CoinStats chart normalization * [BUGFIX] Fix CoinStats processor lint --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
89 lines
2.8 KiB
Ruby
89 lines
2.8 KiB
Ruby
module CoinstatsAccount::ValueHelpers
|
|
extend ActiveSupport::Concern
|
|
|
|
private
|
|
def family_currency
|
|
parse_currency(coinstats_item&.family&.currency)
|
|
end
|
|
|
|
def preferred_exchange_currency
|
|
family_currency.presence || "USD"
|
|
end
|
|
|
|
def exchange_rate_available?(from:, to:)
|
|
return true if from == to
|
|
|
|
ExchangeRate.find_or_fetch_rate(from: from, to: to, date: Date.current).present?
|
|
rescue StandardError => e
|
|
Rails.logger.warn("CoinstatsAccount #{id} - Failed to load FX #{from}/#{to}: #{e.class} - #{e.message}")
|
|
false
|
|
end
|
|
|
|
def converted_usd_amount(raw_usd_amount, target_currency)
|
|
return raw_usd_amount if raw_usd_amount.blank?
|
|
return raw_usd_amount if target_currency == "USD"
|
|
|
|
usd_amount = parse_decimal(raw_usd_amount)
|
|
return if usd_amount.zero? && raw_usd_amount.to_s != "0"
|
|
|
|
return unless exchange_rate_available?(from: "USD", to: target_currency)
|
|
|
|
Money.new(usd_amount, "USD").exchange_to(target_currency).amount
|
|
rescue StandardError => e
|
|
Rails.logger.warn("CoinstatsAccount #{id} - Failed to convert USD -> #{target_currency}: #{e.class} - #{e.message}")
|
|
nil
|
|
end
|
|
|
|
def asset_metadata(payload)
|
|
payload = payload.to_h.with_indifferent_access
|
|
metadata = payload[:coin]
|
|
metadata.is_a?(Hash) ? metadata.with_indifferent_access : payload
|
|
end
|
|
|
|
def extract_currency_amount(value, currency)
|
|
return parse_decimal(value) unless value.is_a?(Hash)
|
|
|
|
values = value.with_indifferent_access
|
|
target_currency = parse_currency(currency) || currency || "USD"
|
|
|
|
parse_decimal(
|
|
values[target_currency] ||
|
|
values[target_currency.to_s] ||
|
|
converted_usd_amount(values[:USD] || values["USD"], target_currency)
|
|
)
|
|
end
|
|
|
|
def exchange_value_payload?(payload)
|
|
exchange_source_for?(payload) || exchange_portfolio_source_for?(payload)
|
|
end
|
|
|
|
def exchange_scalar_value(explicit_value, coin_payload, currency:)
|
|
target_currency = parse_currency(currency) || currency || "USD"
|
|
return parse_decimal(explicit_value) if target_currency == "USD"
|
|
|
|
price_based_value = asset_quantity(coin_payload).abs * asset_price(coin_payload, currency: target_currency)
|
|
return price_based_value if price_based_value.positive?
|
|
|
|
converted_value = converted_usd_amount(explicit_value, target_currency)
|
|
return parse_decimal(converted_value) if converted_value.present?
|
|
|
|
parse_decimal(explicit_value)
|
|
end
|
|
|
|
def fiat_identifier?(value)
|
|
value.to_s.start_with?("FiatCoin")
|
|
end
|
|
|
|
def parse_decimal(value)
|
|
return 0.to_d if value.blank?
|
|
|
|
BigDecimal(value.to_s)
|
|
rescue ArgumentError
|
|
0.to_d
|
|
end
|
|
|
|
def log_invalid_currency(currency_value)
|
|
Rails.logger.warn("Invalid currency code '#{currency_value}' for CoinstatsAccount #{id}, defaulting to USD")
|
|
end
|
|
end
|