monerorequest 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4efb26bf1513834ee0b68535033a34350a5f159adba869ff3e8682d8612cdabf
4
- data.tar.gz: 48ee1c05ae0db4195692ecc06a14bc2a26504982a0c81c9ab8ec1ee390832cb9
3
+ metadata.gz: 1eb8bfed0d690a9ea26e823821d01f213036b54f72dbf0f4b860c81b46860092
4
+ data.tar.gz: 6ff77765db25d97e72f8cdb156bb3077587608bed69a66c947cce6433ffbd717
5
5
  SHA512:
6
- metadata.gz: c27b72a81046b8bf050f0118f5c0cb683b7929a0921ffb592ec45388f99d6bb2c82c9695e9e95225a6a051165f7ac6c2c6bfe6d9520dd2d4f1725d89520d4a1a
7
- data.tar.gz: 65e8f263bf3280a640471114d45658e148725c50dc88d4455c75a3620dc27f0b4e61eced65c9150427ee140f8c72948b7d8899b99a22bc530dcafa3b036605ad
6
+ metadata.gz: ade67de2f1881fa4e46309c0e0a6187a55c7b965199f1e0fa8e1990845d6a28f6217459185e2b3c3026a2334a107f71734c6692a0805ba2995dfac76f630869b
7
+ data.tar.gz: 7f50f46fb99f008027789bf5a528e98cd32d960eaebc9cc8c32dc8a72e124aaa386c89126d216c00f5685c82303253ef562d7fe07904ecfcc8b982a31b499957
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- monerorequest (0.1.0)
4
+ monerorequest (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,24 +1,80 @@
1
1
  # Monerorequest
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
4
-
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/monerorequest`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ ruby gem for encoding and decoding [Monero Payment Request Standard](https://github.com/lukeprofits/Monero_Payment_Request_Standard?tab=readme-ov-file#introduction) requests.
6
4
 
7
5
  ## Installation
8
6
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
-
11
7
  Install the gem and add to the application's Gemfile by executing:
12
8
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
9
+ $ bundle add monerorequest
14
10
 
15
11
  If bundler is not being used to manage dependencies, install the gem by executing:
16
12
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
13
+ $ gem install monerorequest
18
14
 
19
15
  ## Usage
20
16
 
21
- TODO: Write usage instructions here
17
+
18
+ ### V1
19
+ Encode a request:
20
+ ```ruby
21
+ require 'monerorequest'
22
+
23
+ req = {
24
+ "custom_label" => "[some string here]",
25
+ "sellers_wallet" => "[monero main address, starts with 4]",
26
+ "currency" => "USD",
27
+ "amount" => 420.69,
28
+ "payment_id" => "[monero payment ID]",
29
+ "start_date" => "[timestamp in rfc3339 format]",
30
+ "days_per_billing_cycle" => 30,
31
+ "number_of_payments" => 12,
32
+ "change_indicator_url" => "[some url here]"
33
+ }
34
+ enc = Monerorequest::Encoder.new(req)
35
+ enc.encode(1)
36
+ ```
37
+
38
+ Decode a request:
39
+ ```ruby
40
+ require 'monerorequest'
41
+
42
+ req = "monero-request:1:H4sIAAAAAAACAy2QS4vUQBSF/0qondA9XanqJJ3sZjEozGYW4kooKpWbTjmVqnQ9pjuKID7HlStxZiEo4pMBQRAcFPwvCq5c2O0fMD24utxzOR/n3FuItyZoj4o0iWm+k8YjJBqu58CkrqTg3lg
43
+ WrEIFarzvisnEGlOOG5AVaAtSNDuw4m2nYCJsuIkGd7AWtOgHx8GVgwvBedMyxUvYYtafHrz49fT13+8nb+rNnS/nm7ff3v04vb+/fvj8w/WAcQw/3z++dDnai67tbp4cP4ouRP7787M/Z69eJtF+tNycnd/bW9/9+NUN+Ir3jnVgWSmVknrORC8
44
+ UoCKnI6RDWw4XU7OO9y1o71BB8hH6vzFZDYFIlRFe1yTPeVblpB6YDpQC69iSD3P4DZruUtybtGxXcqZS08yrlMeYmMNF1lF+o1FULvzMxwL3C3DikAM/8jSmSpbG9NbWqll1mQtJ6jgJJqFHIe+obDQsLU22NZzn1rOKe9hGwmQ6xskYp1fjWTE
45
+ lBaFjnBUYo9v/ANjVPGWxAQAA"
46
+ dec = Monerorequest::Decoder.new(req)
47
+ dec.decode
48
+ ```
49
+
50
+ ### V2
51
+ Encode a request:
52
+ ```ruby
53
+ require 'monerorequest'
54
+
55
+ req = {
56
+ "custom_label" => "[some string here]",
57
+ "sellers_wallet" => "[monero main address, starts with 4]",
58
+ "currency" => "USD",
59
+ "amount" => 420.69,
60
+ "payment_id" => "[monero payment ID]",
61
+ "start_date" => "[timestamp in rfc3339 format]",
62
+ "schedule" => '* * 1 * *',
63
+ "number_of_payments" => 12,
64
+ "change_indicator_url" => "[some url here]"
65
+ }
66
+ enc = Monerorequest::Encoder.new(req)
67
+ enc.encode(2)
68
+ ```
69
+
70
+ Decode a request:
71
+ ```ruby
72
+ require 'monerorequest'
73
+
74
+ req = "monero-request:2:H4sIAAAAAAACAy2PTW/CMAyG/wrKEVFIE9rS3nbbkcPukZu4JCNNSj6Abtp/X5h2sCw/9vva/iYw++wSGdqm5v2+rXdEanAXFMYpIyH5IHKwZCA6pWU4HIL3Y6XRKHQBjdR7fMK8WDzIkL9IUecQ0Mm1KM7v5z8Qk5+FhRFfNgljKtTlecQg/CQWWGd0KZKB9TvyXwmjyixTHYNpYn0PnerZVHRRalTZYuluN9tNXWL7wmgthigeUHL5hhzfOF19O85Pc7Kt1xfVQk2Zv966hcOnttzc0inVkq43jPIKCPfEa27N6P0awmT1c+libtoILPuG33O/cKMdPgJv4mtlgpCEgvS6hVF2rGhT0fajPg1HNjBe0W6glPz8AihAH5JjAQAA"
75
+ dec = Monerorequest::Decoder.new(req)
76
+ dec.decode
77
+ ```
22
78
 
23
79
  ## Development
24
80
 
@@ -28,7 +84,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
28
84
 
29
85
  ## Contributing
30
86
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/monerorequest.
87
+ Bug reports and pull requests are welcome on GitHub at https://github.com/snex/monerorequest.
32
88
 
33
89
  ## License
34
90
 
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Monerorequest
4
+ # Parses and validates cron syntax string.
5
+ class Cron
6
+ MONTH_CODES = %w[jan feb mar apr may jun jul aug sep oct nov dec].freeze
7
+ DOW_CODES = %w[mon tue wed thu fri sat sun].freeze
8
+ DELIMITERS = %r{,|-|/}.freeze
9
+ def self.valid?(schedule)
10
+ parsed_schedule = parse(schedule)
11
+ return false unless parsed_schedule
12
+
13
+ valid_minutes?(parsed_schedule["minutes"]) && valid_hours?(parsed_schedule["hours"]) &&
14
+ valid_days?(parsed_schedule["days"]) && valid_months?(parsed_schedule["months"]) &&
15
+ valid_dow?(parsed_schedule["dow"])
16
+ end
17
+
18
+ def self.valid_minutes?(minutes)
19
+ minutes.all? { |min| ("0".."59").member?(min) } || minutes == ["*"]
20
+ end
21
+
22
+ def self.valid_hours?(hours)
23
+ hours.all? { |hr| ("0".."23").member?(hr) } || hours == ["*"]
24
+ end
25
+
26
+ def self.valid_days?(days)
27
+ days.all? { |dy| (1..31).member?(dy.to_i) } || days == ["*"]
28
+ end
29
+
30
+ def self.valid_months?(months)
31
+ months.all? { |mth| (1..12).member?(mth.to_i) || MONTH_CODES.include?(mth.downcase) } || months == ["*"]
32
+ end
33
+
34
+ def self.valid_dow?(dow)
35
+ dow.all? { |d| DOW_CODES.include?(d.downcase) } || dow == ["*"]
36
+ end
37
+
38
+ def self.parse(schedule)
39
+ schedule_parts = schedule.split
40
+ return false if schedule_parts.length != 5
41
+
42
+ {
43
+ "minutes" => schedule_parts[0].split(DELIMITERS),
44
+ "hours" => schedule_parts[1].split(DELIMITERS),
45
+ "days" => schedule_parts[2].split(DELIMITERS),
46
+ "months" => schedule_parts[3].split(DELIMITERS),
47
+ "dow" => schedule_parts[4].split(DELIMITERS)
48
+ }
49
+ end
50
+ end
51
+ end
@@ -9,11 +9,13 @@ module Monerorequest
9
9
 
10
10
  def decode
11
11
  _, version, encoded_str = @request.split(":")
12
- raise RequestVersionError, "Only Request Version 1 is supported." unless version == "1"
12
+ raise RequestVersionError, "Request Versions 1 and 2 are supported." unless [1, 2].include?(version.to_i)
13
13
 
14
14
  compressed_data = Base64.decode64(encoded_str)
15
15
  json_str = Zlib::GzipReader.new(StringIO.new(compressed_data)).read
16
- JSON.parse(json_str)
16
+ decoded_hash = JSON.parse(json_str)
17
+ decoded_hash["version"] = version.to_i
18
+ decoded_hash
17
19
  end
18
20
  end
19
21
  end
@@ -23,7 +23,7 @@ module Monerorequest
23
23
  end
24
24
 
25
25
  def encode(version)
26
- raise RequestVersionError, "Only Request Version 1 is supported." unless version == 1
26
+ raise RequestVersionError, "Request Versions 1 and 2 are supported." unless [1, 2].include?(version.to_i)
27
27
 
28
28
  json_str = @request.sort.to_h.to_json.force_encoding("ascii")
29
29
  compressed_data = StringIO.new
@@ -32,7 +32,7 @@ module Monerorequest
32
32
  gz.write(json_str)
33
33
  gz.close
34
34
  encoded_str = Base64.encode64(compressed_data.string).gsub("\n", "")
35
- "monero-request:1:#{encoded_str}"
35
+ "monero-request:#{version}:#{encoded_str}"
36
36
  end
37
37
 
38
38
  private
@@ -44,7 +44,8 @@ module Monerorequest
44
44
  validate_amount!
45
45
  validate_payment_id!
46
46
  validate_start_date!
47
- validate_days_per_billing_cycle!
47
+ validate_days_per_billing_cycle! if @request["version"] == 1
48
+ validate_schedule! if @request["version"] == 2
48
49
  validate_change_indicator_url!
49
50
  end
50
51
 
@@ -88,7 +89,9 @@ module Monerorequest
88
89
  end
89
90
 
90
91
  def validate_days_per_billing_cycle!
91
- @errors.push("days_per_billing_cycle must be present.") unless @request.key?("days_per_billing_cycle")
92
+ unless @request.key?("days_per_billing_cycle") && @request["version"] == "1"
93
+ @errors.push("days_per_billing_cycle must be present.")
94
+ end
92
95
  @errors.push("days_per_billing_cycle must be a Integer.") unless @request["days_per_billing_cycle"].is_a?(Integer)
93
96
  end
94
97
 
@@ -101,5 +104,10 @@ module Monerorequest
101
104
 
102
105
  @errors.push("change_indicator_url must be a URL.")
103
106
  end
107
+
108
+ def validate_schedule!
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", ""))
111
+ end
104
112
  end
105
113
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Monerorequest
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/monerorequest.rb CHANGED
@@ -11,6 +11,7 @@ require_relative "monerorequest/encoder"
11
11
  require_relative "monerorequest/monero_address"
12
12
  require_relative "monerorequest/monero_payment_id"
13
13
  require_relative "monerorequest/version"
14
+ require_relative "monerorequest/cron"
14
15
 
15
16
  module Monerorequest
16
17
  class RequestVersionError < StandardError; end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/monerorequest/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "monerorequest"
7
+ spec.version = Monerorequest::VERSION
8
+ spec.authors = ["David Havlicek"]
9
+ spec.email = ["snex00@protonmail.com"]
10
+
11
+ spec.summary = "Ruby Implementation of the Monero Payment Request Standard. https://github.com/lukeprofits/Monero_Payment_Request_Standard"
12
+ spec.homepage = "https://github.com/snex/monerorequest-ruby"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 2.6.0"
15
+
16
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = spec.homepage
20
+ spec.metadata["changelog_uri"] = "https://github.com/snex/monerorequest-ruby/blob/master/CHANGELOG.md"
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(__dir__) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
27
+ end
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ # Uncomment to register a new dependency of your gem
34
+ # spec.add_dependency "example-gem", "~> 1.0"
35
+
36
+ # For more information and examples about making a new gem, check out our
37
+ # guide at: https://bundler.io/guides/creating_gem.html
38
+ spec.metadata["rubygems_mfa_required"] = "true"
39
+ 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.1.0
4
+ version: 0.2.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: 2024-05-07 00:00:00.000000000 Z
11
+ date: 2025-01-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -26,11 +26,13 @@ files:
26
26
  - README.md
27
27
  - Rakefile
28
28
  - lib/monerorequest.rb
29
+ - lib/monerorequest/cron.rb
29
30
  - lib/monerorequest/decoder.rb
30
31
  - lib/monerorequest/encoder.rb
31
32
  - lib/monerorequest/monero_address.rb
32
33
  - lib/monerorequest/monero_payment_id.rb
33
34
  - lib/monerorequest/version.rb
35
+ - monerorequest.gemspec
34
36
  - sig/monerorequest.rbs
35
37
  homepage: https://github.com/snex/monerorequest-ruby
36
38
  licenses: