bank_of_thailand 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +49 -36
- data/lib/bank_of_thailand/client.rb +7 -4
- data/lib/bank_of_thailand/response.rb +272 -0
- data/lib/bank_of_thailand/version.rb +1 -1
- data/lib/bank_of_thailand.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e4e88cba8f1640985c4d18be3853c7072429a27df7f7d28c9bd490c13321826b
|
|
4
|
+
data.tar.gz: fe6da0cb6c0dd0a3f7f6a782f196bfd9ac969605b44f0f8b83a89af73afa641d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5816fa3b3f30eb7c86bff63ec7e67c95b16730ec73dd570c4187a2cbbaaed5edeccd77150b08d5d18613df959f2c1f56c7a06b3920b7f47be27c2d138953e209
|
|
7
|
+
data.tar.gz: c8e516160e94ca7e361b4088894e76e6e2a686c63fa68c06fff1189ebf1e76c886dee72fbe8656361bace652c9fd8b7fa3e04c1fb66ee59de8570b57d9fd9918
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.0] - 2025-11-04
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Response wrapper class** with comprehensive data analysis utilities
|
|
7
|
+
- Basic statistics: `count`, `first`, `last`, `min`, `max`, `sum`, `average`/`mean`
|
|
8
|
+
- Date range analysis: `date_range`, `period_days`, `complete?`, `missing_dates`
|
|
9
|
+
- Rate change calculations: `change`, `daily_changes`, `volatility`, `trend`
|
|
10
|
+
- CSV export: `to_csv` method for easy data export
|
|
11
|
+
- Backward compatibility: `[]` and `dig` methods for hash-like access
|
|
12
|
+
- Enhanced test coverage (117 examples, 100% pass rate)
|
|
13
|
+
- Updated README with Response class documentation
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- All API methods now return `Response` objects instead of raw hashes
|
|
17
|
+
- Improved error handling for different response formats (arrays, hashes, edge cases)
|
|
18
|
+
|
|
3
19
|
## [0.1.0] - 2025-11-03
|
|
4
20
|
|
|
5
21
|
### Added
|
data/README.md
CHANGED
|
@@ -9,9 +9,10 @@ A Ruby gem for accessing the Bank of Thailand's public API services. This gem pr
|
|
|
9
9
|
|
|
10
10
|
- **Token-based Authentication** - Secure API access using BOT's authorization system
|
|
11
11
|
- **11 API Resources** - Complete coverage of all documented BOT API products
|
|
12
|
+
- **Smart Response Objects** - Built-in statistics, CSV export, and data analysis
|
|
12
13
|
- **Type Safety** - Comprehensive error handling with custom exception classes
|
|
13
14
|
- **Flexible Configuration** - Global or instance-level configuration options
|
|
14
|
-
- **Full Test Coverage** -
|
|
15
|
+
- **Full Test Coverage** - 117 examples with 100% pass rate
|
|
15
16
|
- **YARD Documentation** - Complete API documentation for all endpoints
|
|
16
17
|
|
|
17
18
|
## Installation
|
|
@@ -77,15 +78,7 @@ client = BankOfThailand::Client.new do |config|
|
|
|
77
78
|
end
|
|
78
79
|
```
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
| Option | Type | Default | Description |
|
|
83
|
-
|--------|------|---------|-------------|
|
|
84
|
-
| `api_token` | String | `nil` | **Required.** Your BOT API token from the portal |
|
|
85
|
-
| `base_url` | String | `https://gateway.api.bot.or.th` | Base gateway URL (rarely needs changing) |
|
|
86
|
-
| `timeout` | Integer | `30` | Request timeout in seconds |
|
|
87
|
-
| `max_retries` | Integer | `3` | Number of retry attempts for failed requests |
|
|
88
|
-
| `logger` | Logger | `nil` | Optional logger for debugging |
|
|
81
|
+
**Available Options:** `api_token` (required), `base_url`, `timeout`, `max_retries`, `logger`
|
|
89
82
|
|
|
90
83
|
## Usage
|
|
91
84
|
|
|
@@ -116,6 +109,42 @@ client.financial_holidays # Financial Institutions' Holidays
|
|
|
116
109
|
client.search_series # Search Stat APIs
|
|
117
110
|
```
|
|
118
111
|
|
|
112
|
+
### Working with Responses
|
|
113
|
+
|
|
114
|
+
All API calls return a `Response` object with built-in data analysis features:
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
rates = client.exchange_rate.daily(
|
|
118
|
+
start_period: "2025-01-01",
|
|
119
|
+
end_period: "2025-01-31"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Access data
|
|
123
|
+
rates.data # Array of data points
|
|
124
|
+
rates.count # Number of records
|
|
125
|
+
rates.first # First record
|
|
126
|
+
rates.last # Last record
|
|
127
|
+
|
|
128
|
+
# Quick statistics
|
|
129
|
+
rates.average("value") # Average rate
|
|
130
|
+
rates.min("value") # Minimum rate
|
|
131
|
+
rates.max("value") # Maximum rate
|
|
132
|
+
|
|
133
|
+
# Analyze changes
|
|
134
|
+
rates.change("value") # Overall change with percentage
|
|
135
|
+
rates.volatility("value") # Daily volatility
|
|
136
|
+
rates.trend("value") # :up, :down, or :flat
|
|
137
|
+
|
|
138
|
+
# Export to CSV
|
|
139
|
+
rates.to_csv("rates.csv") # Save to file
|
|
140
|
+
csv_string = rates.to_csv # Get CSV string
|
|
141
|
+
|
|
142
|
+
# Check completeness
|
|
143
|
+
rates.date_range # ["2025-01-01", "2025-01-31"]
|
|
144
|
+
rates.complete? # All dates present?
|
|
145
|
+
rates.missing_dates # Array of missing dates
|
|
146
|
+
```
|
|
147
|
+
|
|
119
148
|
### Exchange Rates
|
|
120
149
|
|
|
121
150
|
#### Weighted-average Interbank Exchange Rate (THB/USD)
|
|
@@ -177,12 +206,6 @@ implied = client.implied_rate.rates(
|
|
|
177
206
|
|
|
178
207
|
### Securities & Markets
|
|
179
208
|
|
|
180
|
-
```ruby
|
|
181
|
-
# Debt securities auction results
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### Securities & Markets
|
|
185
|
-
|
|
186
209
|
```ruby
|
|
187
210
|
# Debt securities auction results
|
|
188
211
|
results = client.debt_securities.auction_results(
|
|
@@ -223,32 +246,22 @@ series = client.search_series.search(keyword: "government debt")
|
|
|
223
246
|
|
|
224
247
|
## Error Handling
|
|
225
248
|
|
|
249
|
+
The gem provides specific exception classes for different error scenarios:
|
|
250
|
+
|
|
226
251
|
```ruby
|
|
227
252
|
begin
|
|
228
|
-
client.exchange_rate.daily
|
|
253
|
+
rates = client.exchange_rate.daily(start_period: "2025-01-01", end_period: "2025-01-31")
|
|
254
|
+
rescue BankOfThailand::AuthenticationError
|
|
255
|
+
puts "Invalid API token"
|
|
229
256
|
rescue BankOfThailand::RateLimitError => e
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
257
|
+
sleep e.retry_after
|
|
258
|
+
retry
|
|
259
|
+
rescue BankOfThailand::RequestError => e
|
|
260
|
+
puts "Request failed: #{e.message}"
|
|
233
261
|
end
|
|
234
262
|
```
|
|
235
263
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
```
|
|
239
|
-
BankOfThailand::Error (StandardError)
|
|
240
|
-
├── ConfigurationError
|
|
241
|
-
└── RequestError
|
|
242
|
-
├── AuthenticationError
|
|
243
|
-
│ └── InvalidTokenError
|
|
244
|
-
├── NotFoundError
|
|
245
|
-
├── RateLimitError
|
|
246
|
-
└── ServerError
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
## Rate Limits
|
|
250
|
-
|
|
251
|
-
Rate limits vary by API product. The gem automatically handles rate limiting errors and provides retry information via `RateLimitError#retry_after`.
|
|
264
|
+
**Exception Types:** `ConfigurationError`, `AuthenticationError`, `NotFoundError`, `RateLimitError`, `ServerError`
|
|
252
265
|
|
|
253
266
|
## Development
|
|
254
267
|
|
|
@@ -149,12 +149,13 @@ module BankOfThailand
|
|
|
149
149
|
|
|
150
150
|
# Handle HTTP response
|
|
151
151
|
# @param response [Faraday::Response] HTTP response
|
|
152
|
-
# @return [
|
|
152
|
+
# @return [Response] Wrapped response object
|
|
153
153
|
# @raise [RequestError] if response indicates an error
|
|
154
154
|
def handle_response(response)
|
|
155
155
|
case response.status
|
|
156
156
|
when 200..299
|
|
157
|
-
parse_json(response.body)
|
|
157
|
+
json = parse_json(response.body)
|
|
158
|
+
Response.new(json)
|
|
158
159
|
when 401
|
|
159
160
|
raise AuthenticationError.new("Authentication failed. Check your API token.", response)
|
|
160
161
|
when 403
|
|
@@ -176,11 +177,13 @@ module BankOfThailand
|
|
|
176
177
|
|
|
177
178
|
# Parse JSON response
|
|
178
179
|
# @param body [String] Response body
|
|
179
|
-
# @return [Hash] Parsed JSON
|
|
180
|
+
# @return [Hash, Array] Parsed JSON
|
|
180
181
|
def parse_json(body)
|
|
181
182
|
return {} if body.nil? || body.empty?
|
|
182
183
|
|
|
183
|
-
JSON.parse(body)
|
|
184
|
+
result = JSON.parse(body)
|
|
185
|
+
# Ensure we return a Hash or Array, not a primitive
|
|
186
|
+
result.is_a?(Hash) || result.is_a?(Array) ? result : {}
|
|
184
187
|
rescue JSON::ParserError => e
|
|
185
188
|
raise RequestError, "Invalid JSON response: #{e.message}"
|
|
186
189
|
end
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "csv"
|
|
4
|
+
require "date"
|
|
5
|
+
|
|
6
|
+
module BankOfThailand
|
|
7
|
+
# Wrapper for API responses with convenience methods
|
|
8
|
+
class Response
|
|
9
|
+
# @return [Hash] the raw API response
|
|
10
|
+
attr_reader :raw
|
|
11
|
+
|
|
12
|
+
# @return [Array<Hash>] the extracted data array
|
|
13
|
+
attr_reader :data
|
|
14
|
+
|
|
15
|
+
# Initialize a new Response
|
|
16
|
+
# @param raw_response [Hash] the raw API response
|
|
17
|
+
def initialize(raw_response)
|
|
18
|
+
@raw = raw_response
|
|
19
|
+
@data = extract_data(raw_response)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Allow hash-like access for backward compatibility
|
|
23
|
+
# @param key [String, Symbol] the key to access
|
|
24
|
+
# @return [Object] the value at the key
|
|
25
|
+
def [](key)
|
|
26
|
+
return nil unless raw.is_a?(Hash)
|
|
27
|
+
|
|
28
|
+
raw[key.to_s]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Allow hash-like dig for backward compatibility
|
|
32
|
+
# @param keys [Array] the keys to dig through
|
|
33
|
+
# @return [Object] the value at the nested keys
|
|
34
|
+
def dig(*keys)
|
|
35
|
+
return nil unless raw.is_a?(Hash)
|
|
36
|
+
|
|
37
|
+
raw.dig(*keys.map(&:to_s))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Count of data points
|
|
41
|
+
# @return [Integer] number of data points
|
|
42
|
+
def count
|
|
43
|
+
data.size
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# First data point
|
|
47
|
+
# @return [Hash, nil] first data point or nil if empty
|
|
48
|
+
def first
|
|
49
|
+
data.first
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Last data point
|
|
53
|
+
# @return [Hash, nil] last data point or nil if empty
|
|
54
|
+
def last
|
|
55
|
+
data.last
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Extract numeric values for a column
|
|
59
|
+
# @param column [String] the column name
|
|
60
|
+
# @return [Array<Float>] array of numeric values
|
|
61
|
+
def values_for(column)
|
|
62
|
+
data.select { |row| row.is_a?(Hash) }.map { |row| row[column]&.to_f }.compact
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Minimum value for a column
|
|
66
|
+
# @param column [String] the column name
|
|
67
|
+
# @return [Float, nil] minimum value or nil if no data
|
|
68
|
+
def min(column)
|
|
69
|
+
values_for(column).min
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Maximum value for a column
|
|
73
|
+
# @param column [String] the column name
|
|
74
|
+
# @return [Float, nil] maximum value or nil if no data
|
|
75
|
+
def max(column)
|
|
76
|
+
values_for(column).max
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Sum of values for a column
|
|
80
|
+
# @param column [String] the column name
|
|
81
|
+
# @return [Float] sum of values
|
|
82
|
+
def sum(column)
|
|
83
|
+
values_for(column).sum
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Average value for a column
|
|
87
|
+
# @param column [String] the column name
|
|
88
|
+
# @return [Float] average value or 0 if no data
|
|
89
|
+
def average(column)
|
|
90
|
+
vals = values_for(column)
|
|
91
|
+
return 0.0 if vals.empty?
|
|
92
|
+
|
|
93
|
+
vals.sum / vals.size.to_f
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
alias mean average
|
|
97
|
+
|
|
98
|
+
# Date range covered by the data
|
|
99
|
+
# @return [Array<String>, nil] [start_date, end_date] or nil if no dates
|
|
100
|
+
def date_range
|
|
101
|
+
dates = data.select { |row| row.is_a?(Hash) }.map { |row| row["period"] || row["date"] }.compact
|
|
102
|
+
return nil if dates.empty?
|
|
103
|
+
|
|
104
|
+
dates.minmax
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Number of days in the period
|
|
108
|
+
# @return [Integer] number of days
|
|
109
|
+
def period_days
|
|
110
|
+
range = date_range
|
|
111
|
+
return 0 unless range
|
|
112
|
+
|
|
113
|
+
(Date.parse(range[1]) - Date.parse(range[0])).to_i + 1
|
|
114
|
+
rescue Date::Error
|
|
115
|
+
0
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Check if data is complete for the date range
|
|
119
|
+
# @return [Boolean] true if all expected days are present
|
|
120
|
+
def complete?
|
|
121
|
+
expected_days = period_days
|
|
122
|
+
return true if expected_days.zero?
|
|
123
|
+
|
|
124
|
+
count >= expected_days
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Find missing dates in the range
|
|
128
|
+
# @return [Array<Date>] array of missing dates
|
|
129
|
+
def missing_dates
|
|
130
|
+
return [] unless date_range
|
|
131
|
+
|
|
132
|
+
start_date = Date.parse(date_range[0])
|
|
133
|
+
end_date = Date.parse(date_range[1])
|
|
134
|
+
actual_dates = data.select { |row| row.is_a?(Hash) }.map { |row| Date.parse(row["period"] || row["date"]) }
|
|
135
|
+
|
|
136
|
+
(start_date..end_date).reject { |date| actual_dates.include?(date) }
|
|
137
|
+
rescue Date::Error
|
|
138
|
+
[]
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Calculate change metrics for a column
|
|
142
|
+
# @param column [String] the column name (default: "value")
|
|
143
|
+
# @return [Hash, nil] hash with :absolute, :percentage, :first_value, :last_value
|
|
144
|
+
def change(column = "value")
|
|
145
|
+
vals = values_for(column)
|
|
146
|
+
return nil if vals.size < 2
|
|
147
|
+
|
|
148
|
+
first_val = vals.first
|
|
149
|
+
last_val = vals.last
|
|
150
|
+
|
|
151
|
+
{
|
|
152
|
+
absolute: last_val - first_val,
|
|
153
|
+
percentage: first_val.zero? ? 0.0 : ((last_val - first_val) / first_val * 100).round(4),
|
|
154
|
+
first_value: first_val,
|
|
155
|
+
last_value: last_val
|
|
156
|
+
}
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Calculate daily changes for a column
|
|
160
|
+
# @param column [String] the column name (default: "value")
|
|
161
|
+
# @return [Array<Hash>] array of change hashes with :absolute and :percentage
|
|
162
|
+
def daily_changes(column = "value")
|
|
163
|
+
vals = values_for(column)
|
|
164
|
+
return [] if vals.size < 2
|
|
165
|
+
|
|
166
|
+
vals.each_cons(2).map do |prev, curr|
|
|
167
|
+
{
|
|
168
|
+
absolute: curr - prev,
|
|
169
|
+
percentage: prev.zero? ? 0.0 : ((curr - prev) / prev * 100).round(4)
|
|
170
|
+
}
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Calculate volatility (standard deviation of daily percentage changes)
|
|
175
|
+
# @param column [String] the column name (default: "value")
|
|
176
|
+
# @return [Float] volatility as standard deviation
|
|
177
|
+
def volatility(column = "value")
|
|
178
|
+
changes = daily_changes(column).map { |c| c[:percentage] }
|
|
179
|
+
return 0.0 if changes.empty?
|
|
180
|
+
|
|
181
|
+
mean = changes.sum / changes.size.to_f
|
|
182
|
+
variance = changes.sum { |x| (x - mean)**2 } / changes.size.to_f
|
|
183
|
+
Math.sqrt(variance).round(4)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Determine trend direction
|
|
187
|
+
# @param column [String] the column name (default: "value")
|
|
188
|
+
# @return [Symbol] :up, :down, or :flat
|
|
189
|
+
def trend(column = "value")
|
|
190
|
+
change_data = change(column)
|
|
191
|
+
return :flat unless change_data
|
|
192
|
+
|
|
193
|
+
pct = change_data[:percentage]
|
|
194
|
+
|
|
195
|
+
if pct > 1
|
|
196
|
+
:up
|
|
197
|
+
elsif pct < -1
|
|
198
|
+
:down
|
|
199
|
+
else
|
|
200
|
+
:flat
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Export data to CSV
|
|
205
|
+
# @param filename [String, nil] optional filename to save CSV
|
|
206
|
+
# @return [String] CSV string or filename if saved
|
|
207
|
+
def to_csv(filename = nil)
|
|
208
|
+
csv_data = CSV.generate do |csv|
|
|
209
|
+
csv << extract_headers
|
|
210
|
+
extract_rows.each { |row| csv << row }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
if filename
|
|
214
|
+
File.write(filename, csv_data)
|
|
215
|
+
filename
|
|
216
|
+
else
|
|
217
|
+
csv_data
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
private
|
|
222
|
+
|
|
223
|
+
# Extract data array from API response
|
|
224
|
+
# @param response [Hash, Array, Object] raw API response
|
|
225
|
+
# @return [Array<Hash>] extracted data array
|
|
226
|
+
def extract_data(response)
|
|
227
|
+
# Handle array responses (e.g., financial holidays)
|
|
228
|
+
return response if response.is_a?(Array)
|
|
229
|
+
|
|
230
|
+
# Handle non-hash/non-array responses
|
|
231
|
+
return [] unless response.is_a?(Hash)
|
|
232
|
+
|
|
233
|
+
# Handle standard BOT API format with result.data
|
|
234
|
+
# Only dig if result exists and is a Hash
|
|
235
|
+
result_data = response["result"]
|
|
236
|
+
return [] unless result_data.is_a?(Hash)
|
|
237
|
+
|
|
238
|
+
result_data["data"] || []
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Extract CSV headers from data
|
|
242
|
+
# @return [Array<String>] array of header names
|
|
243
|
+
def extract_headers
|
|
244
|
+
return [] if data.empty?
|
|
245
|
+
|
|
246
|
+
first_row = data.first
|
|
247
|
+
case first_row
|
|
248
|
+
when Hash
|
|
249
|
+
first_row.keys
|
|
250
|
+
when Array
|
|
251
|
+
(1..first_row.size).map { |i| "column_#{i}" }
|
|
252
|
+
else
|
|
253
|
+
["value"]
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Extract CSV rows from data
|
|
258
|
+
# @return [Array<Array>] array of row arrays
|
|
259
|
+
def extract_rows
|
|
260
|
+
data.map do |row|
|
|
261
|
+
case row
|
|
262
|
+
when Hash
|
|
263
|
+
row.values
|
|
264
|
+
when Array
|
|
265
|
+
row
|
|
266
|
+
else
|
|
267
|
+
[row]
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
data/lib/bank_of_thailand.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "bank_of_thailand/version"
|
|
4
4
|
require_relative "bank_of_thailand/errors"
|
|
5
5
|
require_relative "bank_of_thailand/configuration"
|
|
6
|
+
require_relative "bank_of_thailand/response"
|
|
6
7
|
require_relative "bank_of_thailand/client"
|
|
7
8
|
require_relative "bank_of_thailand/resource"
|
|
8
9
|
require_relative "bank_of_thailand/resources/exchange_rate"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bank_of_thailand
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chayut Orapinpatipat
|
|
@@ -178,6 +178,7 @@ files:
|
|
|
178
178
|
- lib/bank_of_thailand/resources/search_series.rb
|
|
179
179
|
- lib/bank_of_thailand/resources/statistics.rb
|
|
180
180
|
- lib/bank_of_thailand/resources/swap_point.rb
|
|
181
|
+
- lib/bank_of_thailand/response.rb
|
|
181
182
|
- lib/bank_of_thailand/version.rb
|
|
182
183
|
- sig/bank_of_thailand.rbs
|
|
183
184
|
homepage: https://github.com/chayuto/bank_of_thailand
|