79 lines
2 KiB
Ruby
79 lines
2 KiB
Ruby
|
|
# frozen_string_literal: true
|
||
|
|
|
||
|
|
require "json"
|
||
|
|
require "net/http"
|
||
|
|
|
||
|
|
require "provider/adapters/adapter"
|
||
|
|
|
||
|
|
class Provider
|
||
|
|
module Adapters
|
||
|
|
# Nepal Rastra Bank. Publishes daily buy/sell rates for 22 currencies
|
||
|
|
# against NPR. Mid-market rate computed as average of buy and sell.
|
||
|
|
# Rates with unit > 1 (e.g. JPY per 10) are normalized by dividing by unit.
|
||
|
|
class NRB < Adapter
|
||
|
|
BASE_URL = "https://www.nrb.org.np/api/forex/v1/rates"
|
||
|
|
|
||
|
|
class << self
|
||
|
|
def backfill_range = 90
|
||
|
|
end
|
||
|
|
|
||
|
|
def fetch(after: nil, upto: nil)
|
||
|
|
end_date = upto || Date.today
|
||
|
|
dataset = []
|
||
|
|
page = 1
|
||
|
|
|
||
|
|
loop do
|
||
|
|
sleep(0.5) if page > 1
|
||
|
|
url = URI(BASE_URL)
|
||
|
|
url.query = URI.encode_www_form(
|
||
|
|
from: after.to_s,
|
||
|
|
to: end_date.to_s,
|
||
|
|
page: page,
|
||
|
|
per_page: 100,
|
||
|
|
)
|
||
|
|
|
||
|
|
response = Net::HTTP.get(url)
|
||
|
|
data = JSON.parse(response)
|
||
|
|
payload = data.dig("data", "payload") || []
|
||
|
|
dataset.concat(parse(payload))
|
||
|
|
|
||
|
|
pagination = data["pagination"] || {}
|
||
|
|
break if page >= (pagination["pages"] || 1)
|
||
|
|
|
||
|
|
page += 1
|
||
|
|
end
|
||
|
|
|
||
|
|
dataset
|
||
|
|
end
|
||
|
|
|
||
|
|
def parse(payload)
|
||
|
|
payload = JSON.parse(payload) if payload.is_a?(String)
|
||
|
|
return [] unless payload.is_a?(Array)
|
||
|
|
|
||
|
|
payload.flat_map do |day|
|
||
|
|
begin
|
||
|
|
date = Date.parse(day["date"])
|
||
|
|
rescue Date::Error
|
||
|
|
next []
|
||
|
|
end
|
||
|
|
rates = day["rates"] || []
|
||
|
|
|
||
|
|
rates.filter_map do |entry|
|
||
|
|
iso = entry.dig("currency", "iso3")
|
||
|
|
unit = Integer(entry.dig("currency", "unit") || 1)
|
||
|
|
buy = entry["buy"]
|
||
|
|
sell = entry["sell"]
|
||
|
|
next unless buy && sell
|
||
|
|
|
||
|
|
mid = (Float(buy) + Float(sell)) / 2.0
|
||
|
|
rate = mid / unit
|
||
|
|
next if rate.zero?
|
||
|
|
|
||
|
|
{ date:, base: iso, quote: "NPR", rate: }
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|