WIP Verify and respond to zap requests
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
77e2fe5792
commit
c3b82fc2a9
@ -43,7 +43,7 @@ class LnurlpayController < ApplicationController
|
|||||||
|
|
||||||
# GET /lnurlpay/:username/invoice
|
# GET /lnurlpay/:username/invoice
|
||||||
def invoice
|
def invoice
|
||||||
amount = params[:amount].to_i / 1000 # msats
|
amount = params[:amount].to_i / 1000 # msats to sats
|
||||||
comment = params[:comment] || ""
|
comment = params[:comment] || ""
|
||||||
address = @user.address
|
address = @user.address
|
||||||
|
|
||||||
@ -52,6 +52,41 @@ class LnurlpayController < ApplicationController
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if params[:nostr].present?
|
||||||
|
handle_zap_request amount, params[:nostr], params[:lnurl]
|
||||||
|
else
|
||||||
|
handle_pay_request address, amount, comment
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def check_service_available
|
||||||
|
http_status :not_found unless Setting.lndhub_enabled?
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_user
|
||||||
|
@user = User.where(cn: params[:username], ou: Setting.primary_domain).first
|
||||||
|
http_status :not_found if @user.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def metadata(address)
|
||||||
|
"[[\"text/identifier\", \"#{address}\"], [\"text/plain\", \"Send sats, receive thanks.\"]]"
|
||||||
|
end
|
||||||
|
|
||||||
|
def zap_metadata(event)
|
||||||
|
"[[\"application/json\", #{event.to_json}]]"
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_amount?(amount_in_sats)
|
||||||
|
amount_in_sats <= MAX_SATS && amount_in_sats >= MIN_SATS
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_comment?(comment)
|
||||||
|
comment.length <= MAX_COMMENT_CHARS
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_pay_request(address, amount, comment)
|
||||||
if !valid_comment?(comment)
|
if !valid_comment?(comment)
|
||||||
render json: { status: "ERROR", reason: "Comment too long" }
|
render json: { status: "ERROR", reason: "Comment too long" }
|
||||||
return
|
return
|
||||||
@ -61,7 +96,7 @@ class LnurlpayController < ApplicationController
|
|||||||
memo = "#{memo}: \"#{comment}\"" if comment.present?
|
memo = "#{memo}: \"#{comment}\"" if comment.present?
|
||||||
|
|
||||||
payment_request = @user.ln_create_invoice({
|
payment_request = @user.ln_create_invoice({
|
||||||
amount: amount, # we create invoices in sats
|
amount: amount, # sats
|
||||||
memo: memo,
|
memo: memo,
|
||||||
description_hash: Digest::SHA2.hexdigest(metadata(address)),
|
description_hash: Digest::SHA2.hexdigest(metadata(address)),
|
||||||
})
|
})
|
||||||
@ -77,28 +112,37 @@ class LnurlpayController < ApplicationController
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def nostr_event_from_payload(nostr_param)
|
||||||
|
event_obj = JSON.parse(nostr_param).transform_keys(&:to_sym)
|
||||||
def find_user
|
Nostr::Event.new(**event_obj)
|
||||||
@user = User.where(cn: params[:username], ou: Setting.primary_domain).first
|
rescue => e
|
||||||
http_status :not_found if @user.nil?
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def metadata(address)
|
def valid_zap_request?(amount, event, lnurl)
|
||||||
"[[\"text/identifier\", \"#{address}\"], [\"text/plain\", \"Send sats, receive thanks.\"]]"
|
NostrManager::VerifyZapRequest.call(
|
||||||
|
amount: amount, event: event, lnurl: lnurl
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_amount?(amount_in_sats)
|
def handle_zap_request(amount, nostr_param, lnurl_param)
|
||||||
amount_in_sats <= MAX_SATS && amount_in_sats >= MIN_SATS
|
event = nostr_event_from_payload(nostr_param)
|
||||||
|
|
||||||
|
unless event.present? && valid_zap_request?(amount*1000, event, lnurl_param)
|
||||||
|
render json: { status: "ERROR", reason: "Invalid zap request" }
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_comment?(comment)
|
# TODO
|
||||||
comment.length <= MAX_COMMENT_CHARS
|
# raise zap_metadata(event).inspect
|
||||||
end
|
|
||||||
|
|
||||||
private
|
payment_request = @user.ln_create_invoice({
|
||||||
|
amount: amount, # sats
|
||||||
|
# TODO should be npub instead of address?
|
||||||
|
memo: "Zapped #{@user.address} on Nostr", # TODO include event ID if given
|
||||||
|
description_hash: Digest::SHA2.hexdigest(zap_metadata(event)),
|
||||||
|
})
|
||||||
|
|
||||||
def check_service_available
|
render json: { status: "OK", pr: payment_request }
|
||||||
http_status :not_found unless Setting.lndhub_enabled?
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
51
app/services/nostr_manager/verify_zap_request.rb
Normal file
51
app/services/nostr_manager/verify_zap_request.rb
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
module NostrManager
|
||||||
|
class VerifyZapRequest < NostrManagerService
|
||||||
|
def initialize(amount:, event:, lnurl: nil)
|
||||||
|
@amount, @event, @lnurl = amount, event, lnurl
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://github.com/nostr-protocol/nips/blob/27fef638e2460139cc9078427a0aec0ce4470517/57.md#appendix-d-lnurl-server-zap-request-validation
|
||||||
|
def call
|
||||||
|
tags = parse_tags(@event.tags)
|
||||||
|
|
||||||
|
@event.verify_signature &&
|
||||||
|
@event.kind == 9734 &&
|
||||||
|
tags.present? &&
|
||||||
|
valid_p_tag?(tags[:p]) &&
|
||||||
|
valid_e_tag?(tags[:e]) &&
|
||||||
|
valid_a_tag?(tags[:a]) &&
|
||||||
|
valid_amount_tag?(tags[:amount]) &&
|
||||||
|
valid_lnurl_tag?(tags[:lnurl])
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_p_tag?(tag)
|
||||||
|
return false unless tag.present? && tag.length == 1
|
||||||
|
key = Nostr::PublicKey.new(tag.first) rescue nil
|
||||||
|
key.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_e_tag?(tag)
|
||||||
|
return true unless tag.present?
|
||||||
|
# TODO validate format of event ID properly
|
||||||
|
tag.length == 1 && tag.first.is_a?(String)
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_a_tag?(tag)
|
||||||
|
return true unless tag.present?
|
||||||
|
# TODO validate format of event coordinate properly
|
||||||
|
tag.length == 1 && tag.first.is_a?(String)
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_amount_tag?(tag)
|
||||||
|
return true unless tag.present?
|
||||||
|
amount = tag.first
|
||||||
|
amount.is_a?(String) && amount.to_i == @amount
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_lnurl_tag?(tag)
|
||||||
|
return true unless tag.present?
|
||||||
|
# TODO validate lnurl matching recipient's lnurlp
|
||||||
|
tag.first.is_a?(String)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
22
spec/fixtures/nostr/zap_request_event.json
vendored
Normal file
22
spec/fixtures/nostr/zap_request_event.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"kind": 9734,
|
||||||
|
"created_at": 1712066899,
|
||||||
|
"content": "",
|
||||||
|
"tags": [
|
||||||
|
["p", "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"],
|
||||||
|
["amount", "21000"],
|
||||||
|
[
|
||||||
|
"relays",
|
||||||
|
"wss://relay.primal.net",
|
||||||
|
"wss://relay.snort.social",
|
||||||
|
"wss://nostr.wine",
|
||||||
|
"wss://relay.damus.io",
|
||||||
|
"wss://eden.nostr.land",
|
||||||
|
"wss://atlas.nostr.land",
|
||||||
|
"wss://nostr.bitcoiner.social",
|
||||||
|
"wss://relay.mostr.pub",
|
||||||
|
"wss://relay.mostr.pub/",
|
||||||
|
"wss://nostr-01.bolt.observer"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
@ -1,9 +1,8 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe "/lnurlpay", type: :request do
|
RSpec.describe "/lnurlpay", type: :request do
|
||||||
|
|
||||||
context "Non-existent user" do
|
context "Non-existent user" do
|
||||||
describe "GET /.well-known/lnurlpay/:username" do
|
describe "GET /.well-known/lnurlp/:username" do
|
||||||
it "returns a 404" do
|
it "returns a 404" do
|
||||||
get lightning_address_path(username: "csw")
|
get lightning_address_path(username: "csw")
|
||||||
expect(response).to have_http_status(:not_found)
|
expect(response).to have_http_status(:not_found)
|
||||||
@ -32,7 +31,7 @@ RSpec.describe "/lnurlpay", type: :request do
|
|||||||
login_as user, :scope => :user
|
login_as user, :scope => :user
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET /.well-known/lnurlpay/:username" do
|
describe "GET /.well-known/lnurlp/:username" do
|
||||||
it "returns a formatted Lightning Address response" do
|
it "returns a formatted Lightning Address response" do
|
||||||
get lightning_address_path(username: "satoshi")
|
get lightning_address_path(username: "satoshi")
|
||||||
|
|
||||||
@ -67,29 +66,83 @@ RSpec.describe "/lnurlpay", type: :request do
|
|||||||
expect(res["pr"]).to eq("lnbc50u1p3lwgknpp52g78gqya5euvzjc53fc6hkmlm2rfjhcd305tcmc0g9gaestav48sdq4gdhkven9v5sx6mmwv4ujzcqzpgxqyz5vqsp5skkz4jlqr6tkvv2g9739ygrjupc4rkqd94mc7dfpj3pgx3f6w7qs9qyyssq7mf3fzcuxlmkr9nqatcch3u8uf4gjyawe052tejz8e9fqxu4pncqk3qklt8g6ylpshg09xyjquyrgtc72vcw5cp0dzcf406apyua7dgpnfn7an")
|
expect(res["pr"]).to eq("lnbc50u1p3lwgknpp52g78gqya5euvzjc53fc6hkmlm2rfjhcd305tcmc0g9gaestav48sdq4gdhkven9v5sx6mmwv4ujzcqzpgxqyz5vqsp5skkz4jlqr6tkvv2g9739ygrjupc4rkqd94mc7dfpj3pgx3f6w7qs9qyyssq7mf3fzcuxlmkr9nqatcch3u8uf4gjyawe052tejz8e9fqxu4pncqk3qklt8g6ylpshg09xyjquyrgtc72vcw5cp0dzcf406apyua7dgpnfn7an")
|
||||||
end
|
end
|
||||||
|
|
||||||
context "amount too low" do
|
describe "amount too low" do
|
||||||
it "returns an error" do
|
it "returns an error" do
|
||||||
get lnurlpay_invoice_path(username: "satoshi", params: {
|
get lnurlpay_invoice_path(username: "satoshi", params: {
|
||||||
amount: 5000, comment: "Coffee time!"
|
amount: 5000, comment: "Coffee time!"
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
res = JSON.parse(response.body)
|
res = JSON.parse(response.body)
|
||||||
expect(res["status"]).to eq('ERROR')
|
expect(res["status"]).to eq('ERROR')
|
||||||
expect(res["reason"]).to eq('Invalid amount')
|
expect(res["reason"]).to eq('Invalid amount')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "comment too long" do
|
describe "comment too long" do
|
||||||
it "returns an error" do
|
it "returns an error" do
|
||||||
get lnurlpay_invoice_path(username: "satoshi", params: {
|
get lnurlpay_invoice_path(username: "satoshi", params: {
|
||||||
amount: 5000000, comment: "Coffee time is the best time, so here's some money for you to get some. May I suggest to sample some Pacamara beans from El Salvador?"
|
amount: 5000000, comment: "Coffee time is the best time, so here's some money for you to get some. May I suggest to sample some Pacamara beans from El Salvador?"
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
res = JSON.parse(response.body)
|
res = JSON.parse(response.body)
|
||||||
expect(res["status"]).to eq('ERROR')
|
expect(res["status"]).to eq('ERROR')
|
||||||
expect(res["reason"]).to eq('Comment too long')
|
expect(res["reason"]).to eq('Comment too long')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "zap request" do
|
||||||
|
describe "with invalid request event" do
|
||||||
|
it "returns an error" do
|
||||||
|
get lnurlpay_invoice_path(username: "satoshi", params: {
|
||||||
|
amount: 2100000, nostr: { foo: "bar" }.to_json
|
||||||
|
})
|
||||||
|
|
||||||
|
res = JSON.parse(response.body)
|
||||||
|
expect(res["status"]).to eq('ERROR')
|
||||||
|
expect(res["reason"]).to eq('Invalid zap request')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with valid request event" do
|
||||||
|
let(:event) {
|
||||||
|
{
|
||||||
|
id: "3cf02d7f0ccd9711c25098fc50b3a7ab880326e4e51cc8c7a7b59f147cff4fff",
|
||||||
|
pubkey: "730b43e6f62c2ab22710b046e481802c8ac1108ed2cb9c21dff808d57ba24b6c",
|
||||||
|
created_at: 1712487443,
|
||||||
|
kind: 9734,
|
||||||
|
tags: [
|
||||||
|
["relays", "wss://nostr.kosmos.org", "wss://relay.example.com"],
|
||||||
|
["p", "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"]],
|
||||||
|
content: "",
|
||||||
|
sig: "e9e9bb2bac4267a107ab5c3368f504b4f11b8e3b5ae875a1d63c74d6934138d2521dc35815b6f534fc5d803cbf633736d871886368bb8f92c4ad3837a68a06f2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it "returns an invoice" do
|
||||||
|
expect_any_instance_of(User).to receive(:ln_create_invoice)
|
||||||
|
.with(
|
||||||
|
amount: 2100,
|
||||||
|
memo: "Zapped satoshi@kosmos.org on Nostr",
|
||||||
|
description_hash: "540279cd9da15279c8299d6d9ff1ab2a79eb259ee218adf3de393e1abe723077"
|
||||||
|
)
|
||||||
|
.and_return("lnbc50u1p3lwgknpp52g78gqya5euvzjc53fc6hkmlm2rfjhcd305tcmc0g9gaestav48sdq4gdhkven9v5sx6mmwv4ujzcqzpgxqyz5vqsp5skkz4jlqr6tkvv2g9739ygrjupc4rkqd94mc7dfpj3pgx3f6w7qs9qyyssq7mf3fzcuxlmkr9nqatcch3u8uf4gjyawe052tejz8e9fqxu4pncqk3qklt8g6ylpshg09xyjquyrgtc72vcw5cp0dzcf406apyua7dgpnfn7an")
|
||||||
|
|
||||||
|
get lnurlpay_invoice_path(username: "satoshi", params: {
|
||||||
|
amount: 2100000, nostr: event.to_json
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
|
res = JSON.parse(response.body)
|
||||||
|
expect(res["status"]).to eq('OK')
|
||||||
|
expect(res["pr"]).to match(/^lnbc/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET /.well-known/keysend/:username/" do
|
describe "GET /.well-known/keysend/:username/" do
|
||||||
|
206
spec/services/nostr_manager/verify_zap_request_spec.rb
Normal file
206
spec/services/nostr_manager/verify_zap_request_spec.rb
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe NostrManager::VerifyZapRequest, type: :model do
|
||||||
|
describe "Signature invalid" do
|
||||||
|
let(:event) {
|
||||||
|
Nostr::Event.new(
|
||||||
|
id: "3cf02d7f0ccd9711c25098fc50b3a7ab880326e4e51cc8c7a7b59f147cff4fff",
|
||||||
|
pubkey: "730b43e6f62c2ab22710b046e481802c8ac1108ed2cb9c21dff808d57ba24b6c",
|
||||||
|
created_at: 1712487443,
|
||||||
|
kind: 9734,
|
||||||
|
tags: [
|
||||||
|
["relays", "wss://nostr.kosmos.org", "wss://relay.example.com"],
|
||||||
|
["p", "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"]],
|
||||||
|
content: "",
|
||||||
|
sig: "1234562bac4267a107ab5c3368f504b4f11b8e3b5ae875a1d63c74d6934138d2521dc35815b6f534fc5d803cbf633736d871886368bb8f92c4ad3837a68a06f2"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject {
|
||||||
|
NostrManager::VerifyZapRequest.call(amount: 100000, event: event, lnurl: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it "returns false" do
|
||||||
|
expect(subject).to be(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "p tag missing" do
|
||||||
|
let(:event) {
|
||||||
|
Nostr::Event.new(
|
||||||
|
id: "eb53c5e728b625831e318c7ab09373502dd4a41ed11c17f80f32fd1c3fe1252b",
|
||||||
|
pubkey: "730b43e6f62c2ab22710b046e481802c8ac1108ed2cb9c21dff808d57ba24b6c",
|
||||||
|
created_at: 1712580669,
|
||||||
|
kind: 9734,
|
||||||
|
tags: [["relays", "wss://nostr.kosmos.org","wss://relay.example.com"]],
|
||||||
|
content: "",
|
||||||
|
sig: "8e22dcb3e91d080c9549ea0808b018194cc352dde3056a4911796d6f0239de7e1955f287c7e6769909e59ab0ffa09e307178c32128dc451823fb00102ed7e80a"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject {
|
||||||
|
NostrManager::VerifyZapRequest.call(amount: 100000, event: event, lnurl: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it "returns false" do
|
||||||
|
expect(subject).to be(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "p tag not a valid pubkey" do
|
||||||
|
let(:event) {
|
||||||
|
Nostr::Event.new(
|
||||||
|
id: "f2c23f038cf4d0307147d40ddceb87e34ee94acf632f5a67217a55a0b41c5d95",
|
||||||
|
pubkey: "730b43e6f62c2ab22710b046e481802c8ac1108ed2cb9c21dff808d57ba24b6c",
|
||||||
|
created_at: 1712581702,
|
||||||
|
kind: 9734,
|
||||||
|
tags: [
|
||||||
|
["relays", "wss://nostr.kosmos.org","wss://relay.example.com"],
|
||||||
|
["p","123456abcdef"]
|
||||||
|
],
|
||||||
|
content: "",
|
||||||
|
sig: "b33e6b231273d38629f5efb86325ce3b4e02a7d84dfa1f37167ca2de8392cea654ae34000fc365ddfc6e21dc8ce2365fcb000ccb9064fbbcd54c7ea4a943955b"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject {
|
||||||
|
NostrManager::VerifyZapRequest.call(amount: 100000, event: event, lnurl: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it "returns false" do
|
||||||
|
expect(subject).to be(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Minimum valid request" do
|
||||||
|
let(:event) {
|
||||||
|
Nostr::Event.new(
|
||||||
|
id: "3cf02d7f0ccd9711c25098fc50b3a7ab880326e4e51cc8c7a7b59f147cff4fff",
|
||||||
|
pubkey: "730b43e6f62c2ab22710b046e481802c8ac1108ed2cb9c21dff808d57ba24b6c",
|
||||||
|
created_at: 1712487443,
|
||||||
|
kind: 9734,
|
||||||
|
tags: [
|
||||||
|
["relays", "wss://nostr.kosmos.org", "wss://relay.example.com"],
|
||||||
|
["p", "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"]],
|
||||||
|
content: "",
|
||||||
|
sig: "e9e9bb2bac4267a107ab5c3368f504b4f11b8e3b5ae875a1d63c74d6934138d2521dc35815b6f534fc5d803cbf633736d871886368bb8f92c4ad3837a68a06f2"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject {
|
||||||
|
NostrManager::VerifyZapRequest.call(amount: 100000, event: event, lnurl: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it "returns true" do
|
||||||
|
expect(subject).to be(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Optional amount property" do
|
||||||
|
describe "does not match given amount" do
|
||||||
|
let(:event) {
|
||||||
|
Nostr::Event.new(
|
||||||
|
id: "be3d3ba15a257546f6fbba849d4717641fd4ea9f21ae6e9278a045f31d212c5e",
|
||||||
|
pubkey: "730b43e6f62c2ab22710b046e481802c8ac1108ed2cb9c21dff808d57ba24b6c",
|
||||||
|
created_at: 1712579812,
|
||||||
|
kind: 9734,
|
||||||
|
tags: [
|
||||||
|
["relays", "wss://nostr.kosmos.org","wss://relay.example.com"],
|
||||||
|
["p", "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"],
|
||||||
|
["amount", "21000"]
|
||||||
|
],
|
||||||
|
content: "",
|
||||||
|
sig: "2ca9cfd0fdaf43dd8a50ab586e83da4bd9d592def8ed198536f5e3e7aad3537818687e42d98eb61d60e33dbd848c1eecf72b68fd98376bbabdab7e029e810869"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject {
|
||||||
|
NostrManager::VerifyZapRequest.call(amount: 100000, event: event, lnurl: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it "returns false" do
|
||||||
|
expect(subject).to be(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "matches given amount" do
|
||||||
|
let(:event) {
|
||||||
|
Nostr::Event.new(
|
||||||
|
id: "be3d3ba15a257546f6fbba849d4717641fd4ea9f21ae6e9278a045f31d212c5e",
|
||||||
|
pubkey: "730b43e6f62c2ab22710b046e481802c8ac1108ed2cb9c21dff808d57ba24b6c",
|
||||||
|
created_at: 1712579812,
|
||||||
|
kind: 9734,
|
||||||
|
tags: [
|
||||||
|
["relays", "wss://nostr.kosmos.org","wss://relay.example.com"],
|
||||||
|
["p", "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"],
|
||||||
|
["amount", "21000"]
|
||||||
|
],
|
||||||
|
content: "",
|
||||||
|
sig: "2ca9cfd0fdaf43dd8a50ab586e83da4bd9d592def8ed198536f5e3e7aad3537818687e42d98eb61d60e33dbd848c1eecf72b68fd98376bbabdab7e029e810869"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject {
|
||||||
|
NostrManager::VerifyZapRequest.call(amount: 21000, event: event, lnurl: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it "returns true" do
|
||||||
|
expect(subject).to be(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Optional amount property" do
|
||||||
|
describe "does not match given amount" do
|
||||||
|
let(:event) {
|
||||||
|
Nostr::Event.new(
|
||||||
|
id: "be3d3ba15a257546f6fbba849d4717641fd4ea9f21ae6e9278a045f31d212c5e",
|
||||||
|
pubkey: "730b43e6f62c2ab22710b046e481802c8ac1108ed2cb9c21dff808d57ba24b6c",
|
||||||
|
created_at: 1712579812,
|
||||||
|
kind: 9734,
|
||||||
|
tags: [
|
||||||
|
["relays", "wss://nostr.kosmos.org","wss://relay.example.com"],
|
||||||
|
["p", "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"],
|
||||||
|
["amount", "21000"]
|
||||||
|
],
|
||||||
|
content: "",
|
||||||
|
sig: "2ca9cfd0fdaf43dd8a50ab586e83da4bd9d592def8ed198536f5e3e7aad3537818687e42d98eb61d60e33dbd848c1eecf72b68fd98376bbabdab7e029e810869"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject {
|
||||||
|
NostrManager::VerifyZapRequest.call(amount: 100000, event: event, lnurl: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it "returns false" do
|
||||||
|
expect(subject).to be(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "matches given amount" do
|
||||||
|
let(:event) {
|
||||||
|
Nostr::Event.new(
|
||||||
|
id: "be3d3ba15a257546f6fbba849d4717641fd4ea9f21ae6e9278a045f31d212c5e",
|
||||||
|
pubkey: "730b43e6f62c2ab22710b046e481802c8ac1108ed2cb9c21dff808d57ba24b6c",
|
||||||
|
created_at: 1712579812,
|
||||||
|
kind: 9734,
|
||||||
|
tags: [
|
||||||
|
["relays", "wss://nostr.kosmos.org","wss://relay.example.com"],
|
||||||
|
["p", "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"],
|
||||||
|
["amount", "21000"]
|
||||||
|
],
|
||||||
|
content: "",
|
||||||
|
sig: "2ca9cfd0fdaf43dd8a50ab586e83da4bd9d592def8ed198536f5e3e7aad3537818687e42d98eb61d60e33dbd848c1eecf72b68fd98376bbabdab7e029e810869"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject {
|
||||||
|
NostrManager::VerifyZapRequest.call(amount: 21000, event: event, lnurl: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
it "returns true" do
|
||||||
|
expect(subject).to be(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user