diff --git a/lib/faraday_ln_paywall/middleware.rb b/lib/faraday_ln_paywall/middleware.rb index 713ab46..b63d95d 100644 --- a/lib/faraday_ln_paywall/middleware.rb +++ b/lib/faraday_ln_paywall/middleware.rb @@ -4,12 +4,15 @@ require 'lightning/invoice' ENV['GRPC_SSL_CIPHER_SUITES'] = "HIGH+ECDSA" module FaradayLnPaywall + class PaymentError < StandardError; end + class Middleware < Faraday::Middleware def initialize(app, options = {}) super(app) @options = options @options[:address] ||= 'localhost:10009' + @options[:timeout] ||= 5 @options[:credentials] ||= File.read(File.expand_path(@options[:credentials_path] || "~/.lnd/tls.cert")) macaroon_binary ||= File.read(File.expand_path(@options[:macaroon_path] || "~/.lnd/data/chain/bitcoin/testnet/admin.macaroon")) @options[:macaroon] = macaroon_binary.each_byte.map { |b| b.to_s(16).rjust(2,'0') }.join @@ -20,18 +23,25 @@ module FaradayLnPaywall env[:status] == 402 && env[:response_headers]['Content-Type'] == "application/vnd.lightning.bolt11" end - def invoice_valid?(invoice) - (@options[:max_amount].nil? || @options[:max_amount] > invoice.amount) && - invoice.expiry.nil? || Time.now.to_i < invoice.timestamp + invoice.expiry.to_i + def validate_invoice!(invoice) + if !@options[:max_amount].nil? && @options[:max_amount] < invoice.amount + raise PaymentError, "invoice amount greater than expected maximum of #{@options[:max_amount]}" + end + if !invoice.expiry.nil? && Time.now.to_i > invoice.timestamp + invoice.expiry.to_i + raise PaymentError, "invoice expired" + end end def pay(env) invoice = Lightning::Invoice.parse(env.body) - return false unless invoice_valid?(invoice) - @lnd_client.send_payment_sync( - Lnrpc::SendRequest.new(payment_request: env.body), - { metadata: { macaroon: @options[:macaroon] }} - ) + validate_invoice!(invoice) + + Timeout::timeout(@options[:timeout], PaymentError, "payment execution expired") do + @lnd_client.send_payment_sync( + Lnrpc::SendRequest.new(payment_request: env.body), + { metadata: { macaroon: @options[:macaroon] }} + ) + end end def call(request_env) @@ -43,7 +53,7 @@ module FaradayLnPaywall request_env[:request_headers].merge!({'X-Preimage' => preimage}) @app.call(request_env) else - # payment failed + raise PaymentError, payment.payment_error end end end