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 | ||||
|   def invoice | ||||
|     amount = params[:amount].to_i / 1000 # msats | ||||
|     amount = params[:amount].to_i / 1000 # msats to sats | ||||
|     comment = params[:comment] || "" | ||||
|     address = @user.address | ||||
| 
 | ||||
| @ -52,33 +52,19 @@ class LnurlpayController < ApplicationController | ||||
|       return | ||||
|     end | ||||
| 
 | ||||
|     if !valid_comment?(comment) | ||||
|       render json: { status: "ERROR", reason: "Comment too long" } | ||||
|       return | ||||
|     if params[:nostr].present? | ||||
|       handle_zap_request amount, params[:nostr], params[:lnurl] | ||||
|     else | ||||
|       handle_pay_request address, amount, comment | ||||
|     end | ||||
| 
 | ||||
|     memo = "To #{address}" | ||||
|     memo = "#{memo}: \"#{comment}\"" if comment.present? | ||||
| 
 | ||||
|     payment_request = @user.ln_create_invoice({ | ||||
|       amount: amount, # we create invoices in sats | ||||
|       memo: memo, | ||||
|       description_hash: Digest::SHA2.hexdigest(metadata(address)), | ||||
|     }) | ||||
| 
 | ||||
|     render json: { | ||||
|       status: "OK", | ||||
|       successAction: { | ||||
|         tag: "message", | ||||
|         message: "Sats received. Thank you!" | ||||
|       }, | ||||
|       routes: [], | ||||
|       pr: payment_request | ||||
|     } | ||||
|   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? | ||||
| @ -88,6 +74,10 @@ class LnurlpayController < ApplicationController | ||||
|       "[[\"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 | ||||
| @ -96,9 +86,63 @@ class LnurlpayController < ApplicationController | ||||
|       comment.length <= MAX_COMMENT_CHARS | ||||
|     end | ||||
| 
 | ||||
|     private | ||||
|     def handle_pay_request(address, amount, comment) | ||||
|       if !valid_comment?(comment) | ||||
|         render json: { status: "ERROR", reason: "Comment too long" } | ||||
|         return | ||||
|       end | ||||
| 
 | ||||
|     def check_service_available | ||||
|       http_status :not_found unless Setting.lndhub_enabled? | ||||
|       memo = "To #{address}" | ||||
|       memo = "#{memo}: \"#{comment}\"" if comment.present? | ||||
| 
 | ||||
|       payment_request = @user.ln_create_invoice({ | ||||
|         amount: amount, # sats | ||||
|         memo: memo, | ||||
|         description_hash: Digest::SHA2.hexdigest(metadata(address)), | ||||
|       }) | ||||
| 
 | ||||
|       render json: { | ||||
|         status: "OK", | ||||
|         successAction: { | ||||
|           tag: "message", | ||||
|           message: "Sats received. Thank you!" | ||||
|         }, | ||||
|         routes: [], | ||||
|         pr: payment_request | ||||
|       } | ||||
|     end | ||||
| 
 | ||||
|     def nostr_event_from_payload(nostr_param) | ||||
|       event_obj = JSON.parse(nostr_param).transform_keys(&:to_sym) | ||||
|       Nostr::Event.new(**event_obj) | ||||
|     rescue => e | ||||
|       return nil | ||||
|     end | ||||
| 
 | ||||
|     def valid_zap_request?(amount, event, lnurl) | ||||
|       NostrManager::VerifyZapRequest.call( | ||||
|         amount: amount, event: event, lnurl: lnurl | ||||
|       ) | ||||
|     end | ||||
| 
 | ||||
|     def handle_zap_request(amount, nostr_param, lnurl_param) | ||||
|       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 | ||||
| 
 | ||||
|       # TODO | ||||
|       # raise zap_metadata(event).inspect | ||||
| 
 | ||||
|       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)), | ||||
|       }) | ||||
| 
 | ||||
|       render json: { status: "OK", pr: payment_request } | ||||
|     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' | ||||
| 
 | ||||
| RSpec.describe "/lnurlpay", type: :request 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 | ||||
|         get lightning_address_path(username: "csw") | ||||
|         expect(response).to have_http_status(:not_found) | ||||
| @ -32,7 +31,7 @@ RSpec.describe "/lnurlpay", type: :request do | ||||
|       login_as user, :scope => :user | ||||
|     end | ||||
| 
 | ||||
|     describe "GET /.well-known/lnurlpay/:username" do | ||||
|     describe "GET /.well-known/lnurlp/:username" do | ||||
|       it "returns a formatted Lightning Address response" do | ||||
|         get lightning_address_path(username: "satoshi") | ||||
| 
 | ||||
| @ -67,29 +66,83 @@ RSpec.describe "/lnurlpay", type: :request do | ||||
|         expect(res["pr"]).to eq("lnbc50u1p3lwgknpp52g78gqya5euvzjc53fc6hkmlm2rfjhcd305tcmc0g9gaestav48sdq4gdhkven9v5sx6mmwv4ujzcqzpgxqyz5vqsp5skkz4jlqr6tkvv2g9739ygrjupc4rkqd94mc7dfpj3pgx3f6w7qs9qyyssq7mf3fzcuxlmkr9nqatcch3u8uf4gjyawe052tejz8e9fqxu4pncqk3qklt8g6ylpshg09xyjquyrgtc72vcw5cp0dzcf406apyua7dgpnfn7an") | ||||
|       end | ||||
| 
 | ||||
|       context "amount too low" do | ||||
|       describe "amount too low" do | ||||
|         it "returns an error" do | ||||
|           get lnurlpay_invoice_path(username: "satoshi", params: { | ||||
|             amount: 5000, comment: "Coffee time!" | ||||
|           }) | ||||
| 
 | ||||
|           expect(response).to have_http_status(:ok) | ||||
| 
 | ||||
|           res = JSON.parse(response.body) | ||||
|           expect(res["status"]).to eq('ERROR') | ||||
|           expect(res["reason"]).to eq('Invalid amount') | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|       context "comment too long" do | ||||
|       describe "comment too long" do | ||||
|         it "returns an error" do | ||||
|           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?" | ||||
|           }) | ||||
| 
 | ||||
|           expect(response).to have_http_status(:ok) | ||||
| 
 | ||||
|           res = JSON.parse(response.body) | ||||
|           expect(res["status"]).to eq('ERROR') | ||||
|           expect(res["reason"]).to eq('Comment too long') | ||||
|         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 | ||||
| 
 | ||||
|     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