Add LndHub service, lnurl-pay endpoints
Enables the lnurl-pay payment workflow
This commit is contained in:
parent
884070a3cb
commit
dbc811b840
58
app/controllers/lnurlpay_controller.rb
Normal file
58
app/controllers/lnurlpay_controller.rb
Normal file
@ -0,0 +1,58 @@
|
||||
class LnurlpayController < ApplicationController
|
||||
before_action :find_user_by_address
|
||||
|
||||
def index
|
||||
render json: {
|
||||
status: "OK",
|
||||
callback: "https://accounts.kosmos.org/lnurlpay/#{@user.address}/invoice",
|
||||
tag: "payRequest",
|
||||
maxSendable: 1000000,
|
||||
minSendable: 1000,
|
||||
metadata: metadata(@user.address),
|
||||
commentAllowed: 255
|
||||
}
|
||||
end
|
||||
|
||||
def invoice
|
||||
amount = params[:amount].to_i # msats
|
||||
address = params[:address]
|
||||
|
||||
validate_amount(amount)
|
||||
|
||||
# amount = amount / 1000 # we need sats
|
||||
payment_request = @user.ln_create_invoice({
|
||||
amount: amount,
|
||||
description_hash: Digest::SHA2.hexdigest(metadata(address))
|
||||
})
|
||||
|
||||
render json: {
|
||||
status: "OK",
|
||||
successAction: {
|
||||
tag: "message",
|
||||
message: "Payment received. Thanks!"
|
||||
},
|
||||
routes: [],
|
||||
pr: payment_request
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_user_by_address
|
||||
address = params[:address].split("@")
|
||||
@user = User.where(cn: address.first, ou: address.last).first
|
||||
http_status :not_found if @user.nil?
|
||||
end
|
||||
|
||||
def metadata(address)
|
||||
"[[\"text/identifier\", \"#{address}\"], [\"text/plain\", \"Sats for #{address}\"]]"
|
||||
end
|
||||
|
||||
def validate_amount(amount)
|
||||
if amount > 1000000 || amount < 1000
|
||||
render json: { status: "ERROR", reason: "Invalid amount" }
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -27,27 +27,18 @@ class WalletController < ApplicationController
|
||||
if session["ln_auth_token"].present?
|
||||
@ln_auth_token = session["ln_auth_token"]
|
||||
else
|
||||
res = Faraday.post("#{ENV["LNDHUB_API_URL"]}/auth?type=auth",
|
||||
{ login: current_user.ln_login, password: current_user.ln_password }.to_json,
|
||||
"Content-Type" => "application/json",
|
||||
"Accept" => "application/json")
|
||||
|
||||
credentials = JSON.parse(res.body)
|
||||
session["ln_auth_token"] = credentials["access_token"]
|
||||
@ln_auth_token = credentials["access_token"]
|
||||
lndhub = Lndhub.new
|
||||
auth_token = lndhub.authenticate(current_user)
|
||||
session["ln_auth_token"] = auth_token
|
||||
@ln_auth_token = auth_token
|
||||
end
|
||||
rescue
|
||||
# TODO add exception tracking
|
||||
end
|
||||
|
||||
def fetch_balance
|
||||
res = Faraday.get("#{ENV["LNDHUB_API_URL"]}/balance", {}, {
|
||||
"Content-Type" => "application/json",
|
||||
"Accept" => "application/json",
|
||||
"Authorization" => "Bearer #{@ln_auth_token}"
|
||||
})
|
||||
|
||||
data = JSON.parse(res.body)
|
||||
data["BTC"]["AvailableBalance"]
|
||||
lndhub = Lndhub.new
|
||||
data = lndhub.balance @ln_auth_token
|
||||
data["BTC"]["AvailableBalance"]
|
||||
end
|
||||
end
|
||||
|
2
app/helpers/lnurlpay_helper.rb
Normal file
2
app/helpers/lnurlpay_helper.rb
Normal file
@ -0,0 +1,2 @@
|
||||
module LnurlpayHelper
|
||||
end
|
@ -2,14 +2,10 @@ class CreateLndhubWalletJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(user)
|
||||
res = Faraday.post("#{ENV["LNDHUB_API_URL"]}/create",
|
||||
{ partnerid: "bluewallet", accounttype: "common" }.to_json,
|
||||
"Content-Type" => "application/json")
|
||||
|
||||
credentials = JSON.parse(res.body)
|
||||
lndhub = Lndhub.new
|
||||
credentials = lndhub.create({ partnerid: user.ou, accounttype: "user" })
|
||||
|
||||
user.update! ln_login: credentials["login"],
|
||||
ln_password: credentials["password"]
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -56,4 +56,10 @@ class User < ApplicationRecord
|
||||
self.valid?
|
||||
self.errors[attribute_name].blank?
|
||||
end
|
||||
|
||||
def ln_create_invoice(payload)
|
||||
lndhub = Lndhub.new
|
||||
lndhub.authenticate self
|
||||
lndhub.addinvoice payload
|
||||
end
|
||||
end
|
||||
|
57
app/services/lndhub.rb
Normal file
57
app/services/lndhub.rb
Normal file
@ -0,0 +1,57 @@
|
||||
class Lndhub
|
||||
attr_accessor :auth_token
|
||||
|
||||
def initialize
|
||||
@base_url = ENV["LNDHUB_API_URL"]
|
||||
end
|
||||
|
||||
def post(endpoint, payload)
|
||||
headers = { "Content-Type" => "application/json" }
|
||||
if auth_token
|
||||
headers.merge!({ "Authorization" => "Bearer #{auth_token}" })
|
||||
end
|
||||
|
||||
res = Faraday.post "#{@base_url}/#{endpoint}", payload.to_json, headers
|
||||
|
||||
if res.status != 200
|
||||
Rails.logger.error "[lndhub] API request failed:"
|
||||
Rails.logger.error res.body
|
||||
#TODO add some kind of exception tracking/notifications
|
||||
end
|
||||
|
||||
JSON.parse(res.body)
|
||||
end
|
||||
|
||||
def get(endpoint, auth_token)
|
||||
res = Faraday.get("#{@base_url}/#{endpoint}", {}, {
|
||||
"Content-Type" => "application/json",
|
||||
"Accept" => "application/json",
|
||||
"Authorization" => "Bearer #{auth_token}"
|
||||
})
|
||||
|
||||
JSON.parse(res.body)
|
||||
end
|
||||
|
||||
def create(payload)
|
||||
post "create", payload
|
||||
end
|
||||
|
||||
def authenticate(user)
|
||||
credentials = post "auth?type=auth", { login: user.ln_login, password: user.ln_password }
|
||||
self.auth_token = credentials["access_token"]
|
||||
self.auth_token
|
||||
end
|
||||
|
||||
def balance(user_token)
|
||||
get "balance", user_token || auth_token
|
||||
end
|
||||
|
||||
def addinvoice(payload)
|
||||
invoice = post "addinvoice", {
|
||||
amt: payload[:amount],
|
||||
description_hash: payload[:description_hash]
|
||||
}
|
||||
|
||||
invoice["payment_request"]
|
||||
end
|
||||
end
|
@ -21,6 +21,9 @@ Rails.application.routes.draw do
|
||||
|
||||
get 'wallet', to: 'wallet#index'
|
||||
|
||||
get 'lnurlpay/:address', to: 'lnurlpay#index', constraints: { address: /[^\/]+/}
|
||||
get 'lnurlpay/:address/invoice', to: 'lnurlpay#invoice', constraints: { address: /[^\/]+/}
|
||||
|
||||
namespace :admin do
|
||||
root to: 'dashboard#index'
|
||||
get 'invitations', to: 'invitations#index'
|
||||
|
15
spec/helpers/lnurlpay_helper_spec.rb
Normal file
15
spec/helpers/lnurlpay_helper_spec.rb
Normal file
@ -0,0 +1,15 @@
|
||||
require 'rails_helper'
|
||||
|
||||
# Specs in this file have access to a helper object that includes
|
||||
# the LnurlpayHelper. For example:
|
||||
#
|
||||
# describe LnurlpayHelper do
|
||||
# describe "string concat" do
|
||||
# it "concats two strings with spaces" do
|
||||
# expect(helper.concat_strings("this","that")).to eq("this that")
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
RSpec.describe LnurlpayHelper, type: :helper do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
@ -16,7 +16,7 @@ RSpec.describe CreateLndhubWalletJob, type: :job do
|
||||
perform_enqueued_jobs { job }
|
||||
|
||||
expect(WebMock).to have_requested(:post, "http://10.1.1.163:3023/create")
|
||||
.with { |req| req.body == '{"partnerid":"bluewallet","accounttype":"common"}' }
|
||||
.with { |req| req.body == '{"partnerid":"kosmos.org","accounttype":"user"}' }
|
||||
|
||||
user.reload
|
||||
expect(user.ln_login).to eq("abc123")
|
||||
|
7
spec/requests/lnurlpay_spec.rb
Normal file
7
spec/requests/lnurlpay_spec.rb
Normal file
@ -0,0 +1,7 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe "Lnurlpays", type: :request do
|
||||
describe "GET /index" do
|
||||
pending "add some examples (or delete) #{__FILE__}"
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user