monerorequest 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +5 -0
- data/Gemfile.lock +11 -1
- data/README.md +12 -8
- data/lib/monerorequest/cron.rb +6 -4
- data/lib/monerorequest/decoder.rb +31 -9
- data/lib/monerorequest/encoder.rb +22 -89
- data/lib/monerorequest/pipeline/base64_decoder.rb +14 -0
- data/lib/monerorequest/pipeline/base64_encoder.rb +14 -0
- data/lib/monerorequest/pipeline/gzip_reader.rb +15 -0
- data/lib/monerorequest/pipeline/gzip_writer.rb +20 -0
- data/lib/monerorequest/pipeline/json_encoder.rb +16 -0
- data/lib/monerorequest/pipeline/json_parser.rb +14 -0
- data/lib/monerorequest/v1.rb +49 -0
- data/lib/monerorequest/v2.rb +49 -0
- data/lib/monerorequest/validator/amount.rb +16 -0
- data/lib/monerorequest/validator/change_indicator_url.rb +24 -0
- data/lib/monerorequest/validator/currency.rb +15 -0
- data/lib/monerorequest/validator/custom_label.rb +15 -0
- data/lib/monerorequest/validator/days_per_billing_cycle.rb +16 -0
- data/lib/monerorequest/validator/number_of_payments.rb +16 -0
- data/lib/monerorequest/validator/payment_id.rb +15 -0
- data/lib/monerorequest/validator/schedule.rb +15 -0
- data/lib/monerorequest/validator/sellers_wallet.rb +17 -0
- data/lib/monerorequest/validator/start_date.rb +22 -0
- data/lib/monerorequest/version.rb +1 -1
- data/lib/monerorequest.rb +18 -10
- metadata +20 -3
- data/sig/monerorequest.rbs +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 944c04e247c34be236e6071a5b8f384d11f12a21598b487068f8086ef9fdd7cb
|
4
|
+
data.tar.gz: e681abc0a5490f7fa86811a735d53f091b4ab8effd906cfa00b0737db11ba9c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de8f025de01a42d3a6a4cb701e40122e6c115eee4683331da0789e5886f27ce82d99e5fd81811443b5a00c5f62c811ea3d2540bd1036579404fbe869301a5b04
|
7
|
+
data.tar.gz: c81846b18ec909a1c7b84130a17c1b6a7d7b88d884da06aa6634ee915842b4e14d6eaaf862361fa53af48d5f22b21cf56639b07fd2800d67390e1667711602ff
|
data/Gemfile
CHANGED
@@ -6,6 +6,7 @@ source "https://rubygems.org"
|
|
6
6
|
gemspec
|
7
7
|
|
8
8
|
group :development, :test do
|
9
|
+
gem "byebug", "~> 11.1"
|
9
10
|
gem "faker", "~> 3.3"
|
10
11
|
gem "rake", "~> 13.0"
|
11
12
|
gem "rspec", "~> 3.0"
|
@@ -13,3 +14,7 @@ group :development, :test do
|
|
13
14
|
gem "rubocop-rake", "~> 0.6"
|
14
15
|
gem "rubocop-rspec", "~> 2.29"
|
15
16
|
end
|
17
|
+
|
18
|
+
group :test do
|
19
|
+
gem "simplecov", "~> 0.22", require: false
|
20
|
+
end
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
monerorequest (0.
|
4
|
+
monerorequest (1.0.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
ast (2.4.2)
|
10
|
+
byebug (11.1.3)
|
10
11
|
concurrent-ruby (1.2.3)
|
11
12
|
diff-lcs (1.5.1)
|
13
|
+
docile (1.4.1)
|
12
14
|
faker (3.3.1)
|
13
15
|
i18n (>= 1.8.11, < 2)
|
14
16
|
i18n (1.14.5)
|
@@ -64,12 +66,19 @@ GEM
|
|
64
66
|
rubocop-rspec_rails (2.28.3)
|
65
67
|
rubocop (~> 1.40)
|
66
68
|
ruby-progressbar (1.13.0)
|
69
|
+
simplecov (0.22.0)
|
70
|
+
docile (~> 1.1)
|
71
|
+
simplecov-html (~> 0.11)
|
72
|
+
simplecov_json_formatter (~> 0.1)
|
73
|
+
simplecov-html (0.13.1)
|
74
|
+
simplecov_json_formatter (0.1.4)
|
67
75
|
unicode-display_width (2.5.0)
|
68
76
|
|
69
77
|
PLATFORMS
|
70
78
|
x86_64-linux
|
71
79
|
|
72
80
|
DEPENDENCIES
|
81
|
+
byebug (~> 11.1)
|
73
82
|
faker (~> 3.3)
|
74
83
|
monerorequest!
|
75
84
|
rake (~> 13.0)
|
@@ -77,6 +86,7 @@ DEPENDENCIES
|
|
77
86
|
rubocop (~> 1.21)
|
78
87
|
rubocop-rake (~> 0.6)
|
79
88
|
rubocop-rspec (~> 2.29)
|
89
|
+
simplecov (~> 0.22)
|
80
90
|
|
81
91
|
BUNDLED WITH
|
82
92
|
2.4.10
|
data/README.md
CHANGED
@@ -31,18 +31,14 @@ req = {
|
|
31
31
|
"number_of_payments" => 12,
|
32
32
|
"change_indicator_url" => "[some url here]"
|
33
33
|
}
|
34
|
-
enc = Monerorequest::Encoder.new(req)
|
35
|
-
enc.encode(1)
|
34
|
+
enc = Monerorequest::Encoder.new(req, 1)
|
36
35
|
```
|
37
36
|
|
38
37
|
Decode a request:
|
39
38
|
```ruby
|
40
39
|
require 'monerorequest'
|
41
40
|
|
42
|
-
req = "monero-request:1:H4sIAAAAAAACAy2QS4vUQBSF/0qondA9XanqJJ3sZjEozGYW4kooKpWbTjmVqnQ9pjuKID7HlStxZiEo4pMBQRAcFPwvCq5c2O0fMD24utxzOR/n3FuItyZoj4o0iWm+
|
43
|
-
WrEIFarzvisnEGlOOG5AVaAtSNDuw4m2nYCJsuIkGd7AWtOgHx8GVgwvBedMyxUvYYtafHrz49fT13+8nb+rNnS/nm7ff3v04vb+/fvj8w/WAcQw/3z++dDnai67tbp4cP4ouRP7787M/Z69eJtF+tNycnd/bW9/9+NUN+Ir3jnVgWSmVknrORC8
|
44
|
-
UoCKnI6RDWw4XU7OO9y1o71BB8hH6vzFZDYFIlRFe1yTPeVblpB6YDpQC69iSD3P4DZruUtybtGxXcqZS08yrlMeYmMNF1lF+o1FULvzMxwL3C3DikAM/8jSmSpbG9NbWqll1mQtJ6jgJJqFHIe+obDQsLU22NZzn1rOKe9hGwmQ6xskYp1fjWTE
|
45
|
-
lBaFjnBUYo9v/ANjVPGWxAQAA"
|
41
|
+
req = "monero-request:1:H4sIAAAAAAACAy2QS4vUQBSF/0qondA9XanqJJ3sZjEozGYW4kooKpWbTjmVqnQ9pjuKID7HlStxZiEo4pMBQRAcFPwvCq5c2O0fMD24utxzOR/n3FuItyZoj4o0iWm+k8YjJBqu58CkrqTg3lgWrEIFarzvisnEGlOOG5AVaAtSNDuw4m2nYCJsuIkGd7AWtOgHx8GVgwvBedMyxUvYYtafHrz49fT13+8nb+rNnS/nm7ff3v04vb+/fvj8w/WAcQw/3z++dDnai67tbp4cP4ouRP7787M/Z69eJtF+tNycnd/bW9/9+NUN+Ir3jnVgWSmVknrORC8UoCKnI6RDWw4XU7OO9y1o71BB8hH6vzFZDYFIlRFe1yTPeVblpB6YDpQC69iSD3P4DZruUtybtGxXcqZS08yrlMeYmMNF1lF+o1FULvzMxwL3C3DikAM/8jSmSpbG9NbWqll1mQtJ6jgJJqFHIe+obDQsLU22NZzn1rOKe9hGwmQ6xskYp1fjWTElBaFjnBUYo9v/ANjVPGWxAQAA"
|
46
42
|
dec = Monerorequest::Decoder.new(req)
|
47
43
|
dec.decode
|
48
44
|
```
|
@@ -63,8 +59,7 @@ req = {
|
|
63
59
|
"number_of_payments" => 12,
|
64
60
|
"change_indicator_url" => "[some url here]"
|
65
61
|
}
|
66
|
-
enc = Monerorequest::Encoder.new(req)
|
67
|
-
enc.encode(2)
|
62
|
+
enc = Monerorequest::Encoder.new(req, 2)
|
68
63
|
```
|
69
64
|
|
70
65
|
Decode a request:
|
@@ -82,6 +77,15 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
82
77
|
|
83
78
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
84
79
|
|
80
|
+
## Adding a new Monerorequest version
|
81
|
+
|
82
|
+
Adding a new Monerorequest version should be simple.
|
83
|
+
|
84
|
+
1. Update SUPPORTED_MR_VERSIONS in ```lib/monerorequest.rb```.
|
85
|
+
2. Add any necessary pipelines and validators in their respective folders.
|
86
|
+
3. Define a file named "vX.rb" where X is your version that pulls in the pipelines and validators it needs.
|
87
|
+
4. Make sure you add spec coverage for any new code you write and run ```bundle exec rubocop``` to ensure it passes the linter.
|
88
|
+
|
85
89
|
## Contributing
|
86
90
|
|
87
91
|
Bug reports and pull requests are welcome on GitHub at https://github.com/snex/monerorequest.
|
data/lib/monerorequest/cron.rb
CHANGED
@@ -16,19 +16,21 @@ module Monerorequest
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.valid_minutes?(minutes)
|
19
|
-
minutes.all? { |min| ("0".."59").member?(min) } || minutes == ["*"]
|
19
|
+
minutes.all? { |min| ("0".."59").member?(min.to_s) } || minutes == ["*"]
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.valid_hours?(hours)
|
23
|
-
hours.all? { |hr| ("0".."23").member?(hr) } || hours == ["*"]
|
23
|
+
hours.all? { |hr| ("0".."23").member?(hr.to_s) } || hours == ["*"]
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.valid_days?(days)
|
27
|
-
days.all? { |dy| (1..31).member?(dy.
|
27
|
+
days.all? { |dy| ("1".."31").member?(dy.to_s) } || days == ["*"]
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.valid_months?(months)
|
31
|
-
months.all?
|
31
|
+
months.all? do |mth|
|
32
|
+
("1".."12").member?(mth.to_s) || MONTH_CODES.include?(mth.to_s.downcase)
|
33
|
+
end || months == ["*"] || months == ["L"]
|
32
34
|
end
|
33
35
|
|
34
36
|
def self.valid_dow?(dow)
|
@@ -1,21 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
Monerorequest::SUPPORTED_MR_VERSIONS.each do |mr_v|
|
4
|
+
require_relative "v#{mr_v}"
|
5
|
+
end
|
6
|
+
|
3
7
|
module Monerorequest
|
4
|
-
# class to
|
8
|
+
# class to choose a proper Decoder Version and then pass the encoded data to it for decoding
|
5
9
|
class Decoder
|
10
|
+
attr_reader :errors
|
11
|
+
|
6
12
|
def initialize(request)
|
7
13
|
@request = request
|
14
|
+
_, @version, @encoded_str = @request.split(":")
|
15
|
+
raise RequestVersionError, @version unless Monerorequest::SUPPORTED_MR_VERSIONS.include?(@version.to_i)
|
16
|
+
|
17
|
+
@decoder = Object.const_get("Monerorequest::V#{@version}")
|
8
18
|
end
|
9
19
|
|
10
20
|
def decode
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
@data = @encoded_str
|
22
|
+
|
23
|
+
@decoder::Decoder::PIPELINES.each do |pipeline|
|
24
|
+
@data = pipeline.call(@data)
|
25
|
+
end
|
26
|
+
|
27
|
+
@data["version"] = @version.to_i
|
28
|
+
validate!
|
29
|
+
@data
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def validate!
|
35
|
+
@errors = []
|
36
|
+
@decoder::VALIDATORS.each do |validator|
|
37
|
+
@errors += validator.validate!(@data)
|
38
|
+
end
|
39
|
+
|
40
|
+
raise InvalidRequestError, "Invalid request: #{@errors}" unless @errors.empty?
|
19
41
|
end
|
20
42
|
end
|
21
43
|
end
|
@@ -1,113 +1,46 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
require "stringio"
|
7
|
-
require "uri"
|
8
|
-
require "zlib"
|
3
|
+
Monerorequest::SUPPORTED_MR_VERSIONS.each do |mr_v|
|
4
|
+
require_relative "v#{mr_v}"
|
5
|
+
end
|
9
6
|
|
10
7
|
module Monerorequest
|
11
8
|
# class to Encode a Monerorequest hash
|
12
9
|
class Encoder
|
13
|
-
class InvalidRequest < StandardError; end
|
14
|
-
|
15
|
-
attr_accessor :request
|
16
10
|
attr_reader :errors
|
17
11
|
|
18
|
-
def initialize(request)
|
19
|
-
|
20
|
-
@errors = []
|
12
|
+
def initialize(request, version)
|
13
|
+
raise RequestVersionError, version unless Monerorequest::SUPPORTED_MR_VERSIONS.include?(version.to_i)
|
21
14
|
|
15
|
+
@request = request
|
16
|
+
@version = version.to_i
|
17
|
+
set_encoder_version
|
22
18
|
validate!
|
23
19
|
end
|
24
20
|
|
25
|
-
def encode
|
26
|
-
|
27
|
-
|
28
|
-
json_str = @request.sort.to_h.to_json.force_encoding("ascii")
|
29
|
-
compressed_data = StringIO.new
|
30
|
-
gz = Zlib::GzipWriter.new(compressed_data, 9)
|
31
|
-
gz.mtime = 0
|
32
|
-
gz.write(json_str)
|
33
|
-
gz.close
|
34
|
-
encoded_str = Base64.encode64(compressed_data.string).gsub("\n", "")
|
35
|
-
"monero-request:#{version}:#{encoded_str}"
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def validate!
|
41
|
-
validate_custom_label!
|
42
|
-
validate_sellers_wallet!
|
43
|
-
validate_currency!
|
44
|
-
validate_amount!
|
45
|
-
validate_payment_id!
|
46
|
-
validate_start_date!
|
47
|
-
validate_days_per_billing_cycle! if @request["version"] == 1
|
48
|
-
validate_schedule! if @request["version"] == 2
|
49
|
-
validate_change_indicator_url!
|
50
|
-
end
|
51
|
-
|
52
|
-
def validate_custom_label!
|
53
|
-
@errors.push("custom_label must be present.") unless @request.key?("custom_label")
|
54
|
-
@errors.push("custom_label must be a String.") unless @request["custom_label"].is_a?(String)
|
55
|
-
end
|
56
|
-
|
57
|
-
def validate_sellers_wallet!
|
58
|
-
@errors.push("sellers_wallet must be present.") unless @request.key?("sellers_wallet")
|
59
|
-
return if MoneroAddress.valid?(@request["sellers_wallet"])
|
21
|
+
def encode
|
22
|
+
data = @request
|
60
23
|
|
61
|
-
@
|
62
|
-
|
63
|
-
|
64
|
-
def validate_currency!
|
65
|
-
@errors.push("currency must be present.") unless @request.key?("currency")
|
66
|
-
@errors.push("currency must be a String.") unless @request["currency"].is_a?(String)
|
67
|
-
end
|
68
|
-
|
69
|
-
def validate_amount!
|
70
|
-
@errors.push("amount must be present.") unless @request.key?("amount")
|
71
|
-
@errors.push("amount must be a Numeric.") unless @request["amount"].is_a?(Numeric)
|
72
|
-
end
|
24
|
+
@encoder::Encoder::PIPELINES.each do |pipeline|
|
25
|
+
data = pipeline.call(data)
|
26
|
+
end
|
73
27
|
|
74
|
-
|
75
|
-
@errors.push("payment_id must be present.") unless @request.key?("payment_id")
|
76
|
-
@errors.push("payment_id must be a Monero Payment ID.") unless MoneroPaymentID.valid?(@request["payment_id"])
|
28
|
+
"monero-request:#{@version}:#{data}"
|
77
29
|
end
|
78
30
|
|
79
|
-
|
80
|
-
@errors.push("start_date must be present.") unless @request.key?("start_date")
|
81
|
-
unless @request["start_date"].is_a?(String)
|
82
|
-
@errors.push("start_date must be a String.") && @request["start_date"] = ""
|
83
|
-
end
|
84
|
-
begin
|
85
|
-
DateTime.rfc3339(@request["start_date"])
|
86
|
-
rescue Date::Error
|
87
|
-
@errors.push("start_date must be an RFC3339 timestamp.")
|
88
|
-
end
|
89
|
-
end
|
31
|
+
private
|
90
32
|
|
91
|
-
def
|
92
|
-
|
93
|
-
@errors.push("days_per_billing_cycle must be present.")
|
94
|
-
end
|
95
|
-
@errors.push("days_per_billing_cycle must be a Integer.") unless @request["days_per_billing_cycle"].is_a?(Integer)
|
33
|
+
def set_encoder_version
|
34
|
+
@encoder = Object.const_get("Monerorequest::V#{@version}")
|
96
35
|
end
|
97
36
|
|
98
|
-
def
|
99
|
-
@errors
|
100
|
-
|
101
|
-
@errors
|
37
|
+
def validate!
|
38
|
+
@errors = []
|
39
|
+
@encoder::VALIDATORS.each do |validator|
|
40
|
+
@errors += validator.validate!(@request)
|
102
41
|
end
|
103
|
-
return if @request["change_indicator_url"] =~ URI::DEFAULT_PARSER.make_regexp
|
104
|
-
|
105
|
-
@errors.push("change_indicator_url must be a URL.")
|
106
|
-
end
|
107
42
|
|
108
|
-
|
109
|
-
@errors.push("schedule must be present.") unless @request.key?("schedule")
|
110
|
-
@errors.push("schedule must be a valid Cron.") unless Cron.valid?(@request.fetch("schedule", ""))
|
43
|
+
raise InvalidRequestError, "Invalid request: #{@errors}" unless @errors.empty?
|
111
44
|
end
|
112
45
|
end
|
113
46
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "base64"
|
4
|
+
|
5
|
+
module Monerorequest
|
6
|
+
module Pipeline
|
7
|
+
# pipeline that takes a base64 encoded string and decodes it
|
8
|
+
class Base64Decoder
|
9
|
+
def self.call(input)
|
10
|
+
Base64.strict_decode64(input)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "base64"
|
4
|
+
|
5
|
+
module Monerorequest
|
6
|
+
module Pipeline
|
7
|
+
# pipeline that takes a string and base64 encodes it
|
8
|
+
class Base64Encoder
|
9
|
+
def self.call(input)
|
10
|
+
Base64.strict_encode64(input)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
require "zlib"
|
5
|
+
|
6
|
+
module Monerorequest
|
7
|
+
module Pipeline
|
8
|
+
# pipeline that takes a gzip blob and unzips it
|
9
|
+
class GzipReader
|
10
|
+
def self.call(input)
|
11
|
+
Zlib::GzipReader.new(StringIO.new(input)).read
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
require "zlib"
|
5
|
+
|
6
|
+
module Monerorequest
|
7
|
+
module Pipeline
|
8
|
+
# pipeline that takes a string and gzips it
|
9
|
+
class GzipWriter
|
10
|
+
def self.call(input)
|
11
|
+
output = StringIO.new
|
12
|
+
gz = Zlib::GzipWriter.new(output, 9)
|
13
|
+
gz.mtime = 0
|
14
|
+
gz.write(input)
|
15
|
+
gz.close
|
16
|
+
output.string
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module Monerorequest
|
6
|
+
module Pipeline
|
7
|
+
# pipeline that takes a hash, sorts by keys, then converts to valid JSON in ASCII encoding
|
8
|
+
class JSONEncoder
|
9
|
+
def self.call(input)
|
10
|
+
raise InvalidRequestError, "Request must be a Hash." unless input.is_a?(Hash)
|
11
|
+
|
12
|
+
input.sort.to_h.to_json.force_encoding("ascii")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module Monerorequest
|
6
|
+
module Pipeline
|
7
|
+
# pipeline that takes a JSON string and converts it into a ruby object
|
8
|
+
class JSONParser
|
9
|
+
def self.call(input)
|
10
|
+
JSON.parse(input)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "pipeline/base64_decoder"
|
4
|
+
require_relative "pipeline/base64_encoder"
|
5
|
+
require_relative "pipeline/gzip_reader"
|
6
|
+
require_relative "pipeline/gzip_writer"
|
7
|
+
require_relative "pipeline/json_parser"
|
8
|
+
require_relative "pipeline/json_encoder"
|
9
|
+
require_relative "validator/custom_label"
|
10
|
+
require_relative "validator/sellers_wallet"
|
11
|
+
require_relative "validator/currency"
|
12
|
+
require_relative "validator/amount"
|
13
|
+
require_relative "validator/payment_id"
|
14
|
+
require_relative "validator/start_date"
|
15
|
+
require_relative "validator/days_per_billing_cycle"
|
16
|
+
require_relative "validator/number_of_payments"
|
17
|
+
require_relative "validator/change_indicator_url"
|
18
|
+
|
19
|
+
module Monerorequest
|
20
|
+
module V1
|
21
|
+
VALIDATORS = [
|
22
|
+
Monerorequest::Validator::CustomLabel,
|
23
|
+
Monerorequest::Validator::SellersWallet,
|
24
|
+
Monerorequest::Validator::Currency,
|
25
|
+
Monerorequest::Validator::Amount,
|
26
|
+
Monerorequest::Validator::PaymentID,
|
27
|
+
Monerorequest::Validator::StartDate,
|
28
|
+
Monerorequest::Validator::DaysPerBillingCycle,
|
29
|
+
Monerorequest::Validator::NumberOfPayments,
|
30
|
+
Monerorequest::Validator::ChangeIndicatorURL
|
31
|
+
].freeze
|
32
|
+
|
33
|
+
module Encoder
|
34
|
+
PIPELINES = [
|
35
|
+
Monerorequest::Pipeline::JSONEncoder,
|
36
|
+
Monerorequest::Pipeline::GzipWriter,
|
37
|
+
Monerorequest::Pipeline::Base64Encoder
|
38
|
+
].freeze
|
39
|
+
end
|
40
|
+
|
41
|
+
module Decoder
|
42
|
+
PIPELINES = [
|
43
|
+
Monerorequest::Pipeline::Base64Decoder,
|
44
|
+
Monerorequest::Pipeline::GzipReader,
|
45
|
+
Monerorequest::Pipeline::JSONParser
|
46
|
+
].freeze
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "pipeline/base64_decoder"
|
4
|
+
require_relative "pipeline/base64_encoder"
|
5
|
+
require_relative "pipeline/gzip_reader"
|
6
|
+
require_relative "pipeline/gzip_writer"
|
7
|
+
require_relative "pipeline/json_parser"
|
8
|
+
require_relative "pipeline/json_encoder"
|
9
|
+
require_relative "validator/custom_label"
|
10
|
+
require_relative "validator/sellers_wallet"
|
11
|
+
require_relative "validator/currency"
|
12
|
+
require_relative "validator/amount"
|
13
|
+
require_relative "validator/payment_id"
|
14
|
+
require_relative "validator/start_date"
|
15
|
+
require_relative "validator/schedule"
|
16
|
+
require_relative "validator/number_of_payments"
|
17
|
+
require_relative "validator/change_indicator_url"
|
18
|
+
|
19
|
+
module Monerorequest
|
20
|
+
module V2
|
21
|
+
VALIDATORS = [
|
22
|
+
Monerorequest::Validator::CustomLabel,
|
23
|
+
Monerorequest::Validator::SellersWallet,
|
24
|
+
Monerorequest::Validator::Currency,
|
25
|
+
Monerorequest::Validator::Amount,
|
26
|
+
Monerorequest::Validator::PaymentID,
|
27
|
+
Monerorequest::Validator::StartDate,
|
28
|
+
Monerorequest::Validator::Schedule,
|
29
|
+
Monerorequest::Validator::NumberOfPayments,
|
30
|
+
Monerorequest::Validator::ChangeIndicatorURL
|
31
|
+
].freeze
|
32
|
+
|
33
|
+
module Encoder
|
34
|
+
PIPELINES = [
|
35
|
+
Monerorequest::Pipeline::JSONEncoder,
|
36
|
+
Monerorequest::Pipeline::GzipWriter,
|
37
|
+
Monerorequest::Pipeline::Base64Encoder
|
38
|
+
].freeze
|
39
|
+
end
|
40
|
+
|
41
|
+
module Decoder
|
42
|
+
PIPELINES = [
|
43
|
+
Monerorequest::Pipeline::Base64Decoder,
|
44
|
+
Monerorequest::Pipeline::GzipReader,
|
45
|
+
Monerorequest::Pipeline::JSONParser
|
46
|
+
].freeze
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Monerorequest
|
4
|
+
module Validator
|
5
|
+
# validates the amount field
|
6
|
+
class Amount
|
7
|
+
def self.validate!(data)
|
8
|
+
errors = []
|
9
|
+
errors.push("amount must be present.") unless data.key?("amount")
|
10
|
+
errors.push("amount must be a Numeric.") unless data["amount"].is_a?(Numeric)
|
11
|
+
errors.push("amount must be positive.") unless data["amount"].to_f.positive?
|
12
|
+
errors
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
|
5
|
+
module Monerorequest
|
6
|
+
module Validator
|
7
|
+
# validates the change_indicator_url field
|
8
|
+
class ChangeIndicatorURL
|
9
|
+
def self.validate!(data)
|
10
|
+
return [] unless data.key?("change_indicator_url")
|
11
|
+
|
12
|
+
errors = []
|
13
|
+
unless data["change_indicator_url"].is_a?(String)
|
14
|
+
errors.push("change_indicator_url must be a String.")
|
15
|
+
data["change_indicator_url"] = ""
|
16
|
+
end
|
17
|
+
return errors if data["change_indicator_url"] =~ URI::DEFAULT_PARSER.make_regexp
|
18
|
+
|
19
|
+
errors.push("change_indicator_url must be a URL.")
|
20
|
+
errors
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Monerorequest
|
4
|
+
module Validator
|
5
|
+
# validates the currency field
|
6
|
+
class Currency
|
7
|
+
def self.validate!(data)
|
8
|
+
errors = []
|
9
|
+
errors.push("currency must be present.") unless data.key?("currency")
|
10
|
+
errors.push("currency must be a String.") unless data["currency"].is_a?(String)
|
11
|
+
errors
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Monerorequest
|
4
|
+
module Validator
|
5
|
+
# validates the custom_label field
|
6
|
+
class CustomLabel
|
7
|
+
def self.validate!(data)
|
8
|
+
errors = []
|
9
|
+
errors.push("custom_label must be present.") unless data.key?("custom_label")
|
10
|
+
errors.push("custom_label must be a String.") unless data["custom_label"].is_a?(String)
|
11
|
+
errors
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Monerorequest
|
4
|
+
module Validator
|
5
|
+
# validates the days_per_billing_cycle field
|
6
|
+
class DaysPerBillingCycle
|
7
|
+
def self.validate!(data)
|
8
|
+
errors = []
|
9
|
+
errors.push("days_per_billing_cycle must be present.") unless data.key?("days_per_billing_cycle")
|
10
|
+
errors.push("days_per_billing_cycle must be an Integer.") unless data["days_per_billing_cycle"].is_a?(Integer)
|
11
|
+
errors.push("days_per_billing_cycle must be positive.") unless data["days_per_billing_cycle"].to_i.positive?
|
12
|
+
errors
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Monerorequest
|
4
|
+
module Validator
|
5
|
+
# validates the number_of_payments field
|
6
|
+
class NumberOfPayments
|
7
|
+
def self.validate!(data)
|
8
|
+
errors = []
|
9
|
+
errors.push("number_of_payments must be present.") unless data.key?("number_of_payments")
|
10
|
+
errors.push("number_of_payments must be an Integer.") unless data["number_of_payments"].is_a?(Integer)
|
11
|
+
errors.push("number_of_payments must be 0 or positive.") if data["number_of_payments"].to_i.negative?
|
12
|
+
errors
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Monerorequest
|
4
|
+
module Validator
|
5
|
+
# validates the payment_id field
|
6
|
+
class PaymentID
|
7
|
+
def self.validate!(data)
|
8
|
+
errors = []
|
9
|
+
errors.push("payment_id must be present.") unless data.key?("payment_id")
|
10
|
+
errors.push("payment_id must be a Monero Payment ID.") unless MoneroPaymentID.valid?(data["payment_id"])
|
11
|
+
errors
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Monerorequest
|
4
|
+
module Validator
|
5
|
+
# validates the schedule field
|
6
|
+
class Schedule
|
7
|
+
def self.validate!(data)
|
8
|
+
errors = []
|
9
|
+
errors.push("schedule must be present.") unless data.key?("schedule")
|
10
|
+
errors.push("schedule must be a valid Cron.") unless Cron.valid?(data.fetch("schedule", ""))
|
11
|
+
errors
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Monerorequest
|
4
|
+
module Validator
|
5
|
+
# validates the sellers_wallet field
|
6
|
+
class SellersWallet
|
7
|
+
def self.validate!(data)
|
8
|
+
errors = []
|
9
|
+
errors.push("sellers_wallet must be present.") unless data.key?("sellers_wallet")
|
10
|
+
return errors if MoneroAddress.valid?(data["sellers_wallet"])
|
11
|
+
|
12
|
+
errors.push("sellers_wallet must be a main Monero address.")
|
13
|
+
errors
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
|
5
|
+
module Monerorequest
|
6
|
+
module Validator
|
7
|
+
# validates the start_date field
|
8
|
+
class StartDate
|
9
|
+
def self.validate!(data)
|
10
|
+
errors = []
|
11
|
+
errors.push("start_date must be present.") unless data.key?("start_date")
|
12
|
+
errors.push("start_date must be a String.") && data["start_date"] = "" unless data["start_date"].is_a?(String)
|
13
|
+
begin
|
14
|
+
DateTime.rfc3339(data["start_date"])
|
15
|
+
rescue Date::Error
|
16
|
+
errors.push("start_date must be an RFC3339 timestamp.")
|
17
|
+
end
|
18
|
+
errors
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/monerorequest.rb
CHANGED
@@ -1,18 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module Monerorequest
|
4
|
+
SUPPORTED_MR_VERSIONS = [1, 2].freeze
|
5
|
+
|
6
|
+
# error raised when an unsupported Monerorequest version is supplied
|
7
|
+
class RequestVersionError < StandardError
|
8
|
+
def initialize(version)
|
9
|
+
@version = version
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def message
|
14
|
+
"Unknown version: #{@version}. Allowed versions: #{Monerorequest::SUPPORTED_MR_VERSIONS}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class InvalidRequestError < StandardError; end
|
19
|
+
end
|
20
|
+
|
9
21
|
require_relative "monerorequest/decoder"
|
10
22
|
require_relative "monerorequest/encoder"
|
11
23
|
require_relative "monerorequest/monero_address"
|
12
24
|
require_relative "monerorequest/monero_payment_id"
|
13
25
|
require_relative "monerorequest/version"
|
14
26
|
require_relative "monerorequest/cron"
|
15
|
-
|
16
|
-
module Monerorequest
|
17
|
-
class RequestVersionError < StandardError; end
|
18
|
-
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: monerorequest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Havlicek
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-01-
|
11
|
+
date: 2025-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -31,9 +31,26 @@ files:
|
|
31
31
|
- lib/monerorequest/encoder.rb
|
32
32
|
- lib/monerorequest/monero_address.rb
|
33
33
|
- lib/monerorequest/monero_payment_id.rb
|
34
|
+
- lib/monerorequest/pipeline/base64_decoder.rb
|
35
|
+
- lib/monerorequest/pipeline/base64_encoder.rb
|
36
|
+
- lib/monerorequest/pipeline/gzip_reader.rb
|
37
|
+
- lib/monerorequest/pipeline/gzip_writer.rb
|
38
|
+
- lib/monerorequest/pipeline/json_encoder.rb
|
39
|
+
- lib/monerorequest/pipeline/json_parser.rb
|
40
|
+
- lib/monerorequest/v1.rb
|
41
|
+
- lib/monerorequest/v2.rb
|
42
|
+
- lib/monerorequest/validator/amount.rb
|
43
|
+
- lib/monerorequest/validator/change_indicator_url.rb
|
44
|
+
- lib/monerorequest/validator/currency.rb
|
45
|
+
- lib/monerorequest/validator/custom_label.rb
|
46
|
+
- lib/monerorequest/validator/days_per_billing_cycle.rb
|
47
|
+
- lib/monerorequest/validator/number_of_payments.rb
|
48
|
+
- lib/monerorequest/validator/payment_id.rb
|
49
|
+
- lib/monerorequest/validator/schedule.rb
|
50
|
+
- lib/monerorequest/validator/sellers_wallet.rb
|
51
|
+
- lib/monerorequest/validator/start_date.rb
|
34
52
|
- lib/monerorequest/version.rb
|
35
53
|
- monerorequest.gemspec
|
36
|
-
- sig/monerorequest.rbs
|
37
54
|
homepage: https://github.com/snex/monerorequest-ruby
|
38
55
|
licenses:
|
39
56
|
- MIT
|
data/sig/monerorequest.rbs
DELETED