class Money::Bank::TransferwiseBank
TransferwiseBank
base class
Constants
- TW_SANDBOX_SERVICE_HOST
- TW_SERVICE_HOST
TransferwiseBank
url components- TW_SERVICE_PATH
- TW_SERVICE_SSL_VERSION
Default SSL Version
- TW_SOURCE
Default base currency
Attributes
API must have a valid access_key
@param value [String] API access key @return [String] chosen API access key
Cache accessor, can be a String or a Proc
@param value [String,Pathname,Proc] cache system @return [String,Pathname,Proc] chosen cache system
Option to raise an error on failure to connect to the API or parse the response. By default, this is true, but the ability to disable it is useful when developing without an active internet connection.
@example
raise_on_failure = false
@param value [Boolean] should an error be raised on API failure? @return [Boolean] is an error to be raised on API failure?
Parsed TransferwiseBank
result as Hash
Get the timestamp of rates in memory @return [Time] time object or nil
Set the SSL Version used for requests to the API. By default, :TLSv1_2 is used.
@example
service_ssl_version = :TLSv1_1
@param value [Symbol] SSL version from OpenSSL::SSL::SSLContext::METHODS @return [Symbol] chosen SSL version
Set the seconds after than the current rates are automatically expired by default, they never expire.
@example
ttl_in_seconds = 86400 # will expire the rates in one day
@param value [Integer] time to live in seconds @return [Integer] chosen time to live in seconds
Option to use the Sandbox version of the TransferWise API. By default, this is false, and the live API is used.
@example
use_sandbox = true
@param value [Boolean] should the sandbox api be used? @return [Boolean] is the sandbox api being used?
Public Instance Methods
Override Money
`add_rate` method for caching @param [String] from_currency Currency ISO code. ex. 'USD' @param [String] to_currency Currency ISO code. ex. 'CAD' @param [Numeric] rate Rate to use when exchanging currencies. @return [Numeric] rate.
# File lib/money/bank/transferwise_bank.rb, line 178 def add_rate(from_currency, to_currency, rate) super end
Fetch new rates if cached rates are expired or stale @return [Boolean] true if rates are expired and updated from remote
# File lib/money/bank/transferwise_bank.rb, line 198 def expire_rates! if expired? update_rates(true) true elsif stale? update_rates true else false end end
Check if rates are expired @return [Boolean] true if rates are expired
# File lib/money/bank/transferwise_bank.rb, line 212 def expired? Time.now > rates_expiration end
Override Money
`get_rate` method for caching @param [String] from_currency Currency ISO code. ex. 'USD' @param [String] to_currency Currency ISO code. ex. 'CAD' @param [Hash] opts Options hash to set special parameters. @return [Numeric] rate.
# File lib/money/bank/transferwise_bank.rb, line 190 def get_rate(from_currency, to_currency, opts = {}) expire_rates! rate = get_rate_or_calc_inverse(from_currency, to_currency, opts) rate || calc_pair_rate_using_base(from_currency, to_currency, opts) end
Option to raise an error on failure to connect to the API or parse the response. By default, this is true, but the ability to disable it is useful when developing without an active internet connection. @return [Boolean] is an error to be raised on API failure?
# File lib/money/bank/transferwise_bank.rb, line 150 def raise_on_failure @raise_on_failure = true if @raise_on_failure.nil? @raise_on_failure end
Get rates expiration time based on ttl @return [Time] rates expiration time
# File lib/money/bank/transferwise_bank.rb, line 245 def rates_expiration rates_timestamp + ttl_in_seconds end
Get the timestamp of rates from first listed rate @return [Time] time object or nil
# File lib/money/bank/transferwise_bank.rb, line 251 def rates_timestamp raw = raw_rates_careful raw.first.key?('time') ? Time.parse(raw.first['time']) : Time.at(0) end
Service host of TransferwiseBank
API based on value of 'use_sandbox' option. @return [String] the remote API service host
# File lib/money/bank/transferwise_bank.rb, line 227 def service_host use_sandbox ? TW_SANDBOX_SERVICE_HOST : TW_SERVICE_HOST end
Set the SSL Version used for requests to the API. By default, :TLSv1_2 is used. @return [Symbol] chosen SSL version
# File lib/money/bank/transferwise_bank.rb, line 134 def service_ssl_version @service_ssl_version ||= TW_SERVICE_SSL_VERSION end
Get the base currency for all rates. By default, USD is used. @return [String] base currency
# File lib/money/bank/transferwise_bank.rb, line 120 def source @source ||= TW_SOURCE end
Set the base currency for all rates. By default, USD is used. TransferwiseBank
only allows USD as base currency for the free plan users.
@example
source = 'USD'
@param value [String] Currency code, ISO 3166-1 alpha-3 @return [String] chosen base currency
# File lib/money/bank/transferwise_bank.rb, line 114 def source=(value) @source = Money::Currency.find(value.to_s).try(:iso_code) || TW_SOURCE end
Source url of TransferwiseBank
@return [String] the remote API url
# File lib/money/bank/transferwise_bank.rb, line 233 def source_url raise NoAccessKey if access_key.nil? || access_key.empty? url_componenets = { host: service_host, path: TW_SERVICE_PATH, query: "source=#{source}" } URI::HTTPS.build(url_componenets) end
Check if rates are stale Stale is true if rates are updated straight by another thread. The actual thread has always old rates in memory store. @return [Boolean] true if rates are stale
# File lib/money/bank/transferwise_bank.rb, line 220 def stale? rates_timestamp != rates_mem_timestamp end
Get the seconds after than the current rates are automatically expired by default, they never expire. @return [Integer] chosen time to live in seconds
# File lib/money/bank/transferwise_bank.rb, line 127 def ttl_in_seconds @ttl_in_seconds ||= 0 end
Update all rates from TrasferwiseBank JSON @return [Array] array of exchange rates
# File lib/money/bank/transferwise_bank.rb, line 157 def update_rates(straight = false) new_rates = exchange_rates(straight) return if new_rates.first.empty? store.reset! rates = new_rates.each do |exchange_rate| currency = exchange_rate['target'] rate = exchange_rate['rate'] next unless Money::Currency.find(currency) add_rate(source, currency, rate) add_rate(currency, source, 1.0 / rate) end add_rate(source, source, 1.0) @rates_mem_timestamp = rates_timestamp rates end
Option to use the Sandbox version of the TransferWise API. By default, this is false, and the live API is used. @return [Boolean] is the sandbox api being used?
# File lib/money/bank/transferwise_bank.rb, line 141 def use_sandbox @use_sandbox = false if @use_sandbox.nil? @use_sandbox end
Protected Instance Methods
Tries to calculate a pair rate using base currency rate @param [String] from_currency Currency ISO code. ex. 'USD' @param [String] to_currency Currency ISO code. ex. 'CAD' @return [Numeric] rate or nil if cannot calculate rate.
# File lib/money/bank/transferwise_bank.rb, line 394 def calc_pair_rate_using_base(from_currency, to_currency, opts = {}) from_base_rate = get_rate_or_calc_inverse(source, from_currency, opts) to_base_rate = get_rate_or_calc_inverse(source, to_currency, opts) if to_base_rate && from_base_rate rate = to_base_rate / from_base_rate add_rate(from_currency, to_currency, rate) return rate end nil end
Get exchange rates with different strategies
@example
exchange_rates(true) exchange_rates
@param straight [Boolean] true for straight, default is careful @return [Hash] key is country code (ISO 3166-1 alpha-3) value Float
# File lib/money/bank/transferwise_bank.rb, line 348 def exchange_rates(straight = false) @rates = if straight raw_rates_straight else raw_rates_careful end end
Get rate or calculate it as inverse rate @param [String] from_currency Currency ISO code. ex. 'USD' @param [String] to_currency Currency ISO code. ex. 'CAD' @return [Numeric] rate or rate calculated as inverse rate.
# File lib/money/bank/transferwise_bank.rb, line 377 def get_rate_or_calc_inverse(from_currency, to_currency, opts = {}) rate = super_get_rate(from_currency, to_currency, opts) unless rate # Tries to calculate an inverse rate inverse_rate = super_get_rate(to_currency, from_currency, opts) if inverse_rate rate = 1.0 / inverse_rate add_rate(from_currency, to_currency, rate) end end rate end
Opens an file and reads the content @return [String] unparsed JSON content
# File lib/money/bank/transferwise_bank.rb, line 306 def open_file open(source_url).read rescue OpenURI::HTTPError '' end
Get raw exchange rates from cache and then from url @param rescue_straight [Boolean] true for rescue straight, default true @return [String] JSON content
# File lib/money/bank/transferwise_bank.rb, line 359 def raw_rates_careful(rescue_straight = true) JSON.parse(read_from_cache.to_s) rescue JSON::ParserError, TypeError rescue_straight ? raw_rates_straight : [{}] end
Get raw exchange rates from url @return [String] JSON content
# File lib/money/bank/transferwise_bank.rb, line 367 def raw_rates_straight JSON.parse(read_from_url) rescue JSON::ParserError, TypeError raw_rates_careful(false) end
Read from cache when exist @return [Proc,String] parsed JSON content
# File lib/money/bank/transferwise_bank.rb, line 287 def read_from_cache if cache.is_a?(Proc) cache.call(nil) elsif (cache.is_a?(String) || cache.is_a?(Pathname)) && File.exist?(cache) open(cache).read end end
Get remote content and store in cache @return [String] unparsed JSON content
# File lib/money/bank/transferwise_bank.rb, line 298 def read_from_url rates = source_url.is_a?(URI::HTTPS) ? retrieve_rates : open_file store_in_cache(rates) if valid_rates?(rates) && cache rates end
Opens an url and reads the content @return [String] unparsed JSON content
# File lib/money/bank/transferwise_bank.rb, line 314 def retrieve_rates response = HTTParty.get( source_url, headers: { 'Authorization' => "Bearer #{access_key}" }, ssl_version: service_ssl_version ) response.body rescue HTTParty::Error, SocketError => e raise e if raise_on_failure [{}] end
Store the provided text data by calling the proc method provided for the cache, or write to the cache file.
@example
store_in_cache("{\"quotes\": {\"USDAED\": 3.67304}}")
@param text [String] parsed JSON content @return [String,Integer]
# File lib/money/bank/transferwise_bank.rb, line 266 def store_in_cache(text) if cache.is_a?(Proc) cache.call(text) elsif cache.is_a?(String) || cache.is_a?(Pathname) write_to_file(text) end end
Check validity of rates response only for store in cache
@example
valid_rates?("{\"quotes\": {\"USDAED\": 3.67304}}")
@param [String] text is JSON content @return [Boolean] valid or not
# File lib/money/bank/transferwise_bank.rb, line 333 def valid_rates?(text) parsed = JSON.parse(text) parsed && parsed.is_a?(Array) && !parsed.first.empty? rescue JSON::ParserError, TypeError false end
Writes content to file cache @param text [String] parsed JSON content @return [String,Integer]
# File lib/money/bank/transferwise_bank.rb, line 277 def write_to_file(text) open(cache, 'w') do |f| f.write(text) end rescue Errno::ENOENT raise InvalidCache end