# frozen_string_literal: true require "net/http" require "ox" require "provider/adapters/adapter" class Provider module Adapters # Central Bank of Armenia. Publishes daily rates for ~30 currencies against AMD. class CBA < Adapter URL = URI("https://api.cba.am/exchangerates.asmx") CHUNK_SIZE = 365 TROY_OUNCE_GRAMS = 31.1035 PRECIOUS_METALS = ["XAU", "XAG"].freeze def fetch(after: nil, upto: nil) end_date = upto || Date.today iso_codes = current_currency_codes records = [] chunk_start = after while chunk_start <= end_date chunk_end = [chunk_start + CHUNK_SIZE - 1, end_date].min records.concat(range(chunk_start, chunk_end, iso_codes)) chunk_start = chunk_end + 1 end records end private def current_currency_codes response = request("ExchangeRatesLatest", <<~XML) XML result = response.locate("soap:Envelope/soap:Body/ExchangeRatesLatestResponse/ExchangeRatesLatestResult").first return "" unless result result.locate("Rates/ExchangeRate").filter_map do |node| node.locate("ISO").first&.text end.join(",") end def range(start_date, end_date, iso_codes) response = request("ExchangeRatesByDateRangeByISO", <<~XML) #{iso_codes} #{start_date} #{end_date} XML response .locate("soap:Envelope/soap:Body/ExchangeRatesByDateRangeByISOResponse/ExchangeRatesByDateRangeByISOResult/diffgr:diffgram/DocumentElement/ExchangeRatesByRange") .filter_map do |row| iso = row.locate("ISO").first&.text next unless iso { date: Date.parse(row.locate("RateDate").first.text), base: iso, quote: "AMD", rate: extract_rate(row) } end end def request(action, payload) xml = <<~XML #{payload.strip} XML Ox.load( Net::HTTP.post( URL, xml, { "Content-Type" => "text/xml; charset=utf-8", "SOAPAction" => "\"http://www.cba.am/#{action}\"", }, ).body, ) end def extract_rate(node) iso = node.locate("ISO").first&.text amount = Integer(node.locate("Amount").first.text) rate = Float(node.locate("Rate").first.text) rate *= TROY_OUNCE_GRAMS if PRECIOUS_METALS.include?(iso) rate / amount end end end end