Merge pull request 'Add keysend support for Lightning Addresses, specs for address/lnurlp responses' (#84) from feature/ln_address_keysend into master
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #84 Reviewed-by: bumi <bumi@noreply.kosmos.org>
This commit is contained in:
commit
1142a4e2d5
@ -11,6 +11,7 @@ BTCPAY_API_URL='http://localhost:23001/api/v1'
|
|||||||
|
|
||||||
LNDHUB_API_URL='http://localhost:3023'
|
LNDHUB_API_URL='http://localhost:3023'
|
||||||
LNDHUB_PUBLIC_URL='https://lndhub.kosmos.org'
|
LNDHUB_PUBLIC_URL='https://lndhub.kosmos.org'
|
||||||
|
LNDHUB_PUBLIC_KEY='0123d3be18617f39cf645851e3ba63f51fc13f0bb09e3bb25e6fd4de556486d946'
|
||||||
LNDHUB_ADMIN_UI=true
|
LNDHUB_ADMIN_UI=true
|
||||||
LNDHUB_PG_HOST=localhost
|
LNDHUB_PG_HOST=localhost
|
||||||
LNDHUB_PG_PORT=5432
|
LNDHUB_PG_PORT=5432
|
||||||
|
@ -4,5 +4,6 @@ BTCPAY_API_URL='http://btcpay.example.com/api/v1'
|
|||||||
|
|
||||||
LNDHUB_API_URL='http://localhost:3026'
|
LNDHUB_API_URL='http://localhost:3026'
|
||||||
LNDHUB_PUBLIC_URL='https://lndhub.kosmos.org'
|
LNDHUB_PUBLIC_URL='https://lndhub.kosmos.org'
|
||||||
|
LNDHUB_PUBLIC_KEY='024cd3be18617f39cf645851e3ba63f51fc13f0bb09e3bb25e6fd4de556486d946'
|
||||||
|
|
||||||
WEBHOOKS_ALLOWED_IPS='10.1.1.23'
|
WEBHOOKS_ALLOWED_IPS='10.1.1.23'
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
class LnurlpayController < ApplicationController
|
class LnurlpayController < ApplicationController
|
||||||
|
before_action :check_feature_enabled
|
||||||
before_action :find_user_by_address
|
before_action :find_user_by_address
|
||||||
|
|
||||||
MIN_SATS = 10
|
MIN_SATS = 10
|
||||||
@ -17,6 +18,20 @@ class LnurlpayController < ApplicationController
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def keysend
|
||||||
|
http_status :not_found and return unless Setting.lndhub_keysend_enabled?
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
status: "OK",
|
||||||
|
tag: "keysend",
|
||||||
|
pubkey: Setting.lndhub_public_key,
|
||||||
|
customData: [{
|
||||||
|
customKey: "696969",
|
||||||
|
customValue: @user.ln_account
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def invoice
|
def invoice
|
||||||
amount = params[:amount].to_i / 1000 # msats
|
amount = params[:amount].to_i / 1000 # msats
|
||||||
address = params[:address]
|
address = params[:address]
|
||||||
@ -72,4 +87,9 @@ class LnurlpayController < ApplicationController
|
|||||||
comment.length <= MAX_COMMENT_CHARS
|
comment.length <= MAX_COMMENT_CHARS
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def check_feature_enabled
|
||||||
|
http_status :not_found unless Setting.lndhub_enabled?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -2,10 +2,27 @@
|
|||||||
class Setting < RailsSettings::Base
|
class Setting < RailsSettings::Base
|
||||||
cache_prefix { "v1" }
|
cache_prefix { "v1" }
|
||||||
|
|
||||||
|
#
|
||||||
|
# Registrations
|
||||||
|
#
|
||||||
|
|
||||||
field :reserved_usernames, type: :array, default: %w[
|
field :reserved_usernames, type: :array, default: %w[
|
||||||
account accounts donations mail webmaster support
|
account accounts donations mail webmaster support
|
||||||
]
|
]
|
||||||
|
|
||||||
field :lndhub_enabled, default: (ENV["LNDHUB_API_URL"].present?.to_s || "false"), type: :boolean
|
#
|
||||||
field :lndhub_admin_enabled, default: (ENV["LNDHUB_ADMIN_UI"] || "false"), type: :boolean
|
# Lightning Network
|
||||||
|
#
|
||||||
|
|
||||||
|
field :lndhub_enabled, type: :boolean,
|
||||||
|
default: (ENV["LNDHUB_API_URL"].present?.to_s || false)
|
||||||
|
|
||||||
|
field :lndhub_admin_enabled, type: :boolean,
|
||||||
|
default: (ENV["LNDHUB_ADMIN_UI"] || false)
|
||||||
|
|
||||||
|
field :lndhub_public_key, type: :string,
|
||||||
|
default: (ENV["LNDHUB_PUBLIC_KEY"] || "")
|
||||||
|
|
||||||
|
field :lndhub_keysend_enabled, type: :boolean,
|
||||||
|
default: -> { self.lndhub_public_key.present?.to_s || false }
|
||||||
end
|
end
|
||||||
|
@ -28,8 +28,12 @@ Rails.application.routes.draw do
|
|||||||
get 'wallet', to: 'wallet#index'
|
get 'wallet', to: 'wallet#index'
|
||||||
get 'wallet/transactions', to: 'wallet#transactions'
|
get 'wallet/transactions', to: 'wallet#transactions'
|
||||||
|
|
||||||
get 'lnurlpay/:address', to: 'lnurlpay#index', constraints: { address: /[^\/]+/}
|
get 'lnurlpay/:address', to: 'lnurlpay#index',
|
||||||
get 'lnurlpay/:address/invoice', to: 'lnurlpay#invoice', constraints: { address: /[^\/]+/}
|
as: 'lightning_address', constraints: { address: /[^\/]+/}
|
||||||
|
get 'lnurlpay/:address/invoice', to: 'lnurlpay#invoice',
|
||||||
|
as: 'lnurlpay_invoice', constraints: { address: /[^\/]+/}
|
||||||
|
get 'keysend/:address', to: 'lnurlpay#keysend',
|
||||||
|
as: 'lightning_address_keysend', constraints: { address: /[^\/]+/}
|
||||||
|
|
||||||
post 'webhooks/lndhub', to: 'webhooks#lndhub'
|
post 'webhooks/lndhub', to: 'webhooks#lndhub'
|
||||||
|
|
||||||
|
110
spec/requests/lnurlpay_spec.rb
Normal file
110
spec/requests/lnurlpay_spec.rb
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe "/lnurlpay", type: :request do
|
||||||
|
|
||||||
|
context "Non-existent user/address" do
|
||||||
|
describe "GET /lnurlpay/:address" do
|
||||||
|
it "returns a 404" do
|
||||||
|
get lightning_address_path(address: "csw@kosmos.org")
|
||||||
|
expect(response).to have_http_status(:not_found)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET /lnurlpay/:address/invoice" do
|
||||||
|
it "returns a 404" do
|
||||||
|
get lnurlpay_invoice_path(address: "csw@kosmos.org", params: { amount: 5000 })
|
||||||
|
expect(response).to have_http_status(:not_found)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET /keysend/:address/" do
|
||||||
|
it "returns a 404" do
|
||||||
|
get lightning_address_keysend_path(address: "csw@kosmos.org")
|
||||||
|
expect(response).to have_http_status(:not_found)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "Valid user/address" do
|
||||||
|
let(:user) { create :user, cn: 'satoshi', ou: 'kosmos.org', ln_account: 'abcdefg123456' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
login_as user, :scope => :user
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET /lnurlpay/:address" do
|
||||||
|
it "returns a formatted Lightning Address response" do
|
||||||
|
get lightning_address_path(address: "satoshi@kosmos.org")
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
|
res = JSON.parse(response.body)
|
||||||
|
expect(res["status"]).to eq('OK')
|
||||||
|
expect(res["tag"]).to eq('payRequest')
|
||||||
|
expect(res["callback"]).to match(lnurlpay_invoice_path('satoshi@kosmos.org'))
|
||||||
|
expect(res["minSendable"]).to be_a(Integer)
|
||||||
|
expect(res["maxSendable"]).to be_a(Integer)
|
||||||
|
expect(res["commentAllowed"]).to be_a(Integer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET /lnurlpay/:address/invoice" do
|
||||||
|
before do
|
||||||
|
allow_any_instance_of(User).to receive(:ln_create_invoice).and_return("lnbc50u1p3lwgknpp52g78gqya5euvzjc53fc6hkmlm2rfjhcd305tcmc0g9gaestav48sdq4gdhkven9v5sx6mmwv4ujzcqzpgxqyz5vqsp5skkz4jlqr6tkvv2g9739ygrjupc4rkqd94mc7dfpj3pgx3f6w7qs9qyyssq7mf3fzcuxlmkr9nqatcch3u8uf4gjyawe052tejz8e9fqxu4pncqk3qklt8g6ylpshg09xyjquyrgtc72vcw5cp0dzcf406apyua7dgpnfn7an")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a formatted lnurlpay response" do
|
||||||
|
get lnurlpay_invoice_path(address: "satoshi@kosmos.org", params: {
|
||||||
|
amount: 50000, comment: "Coffee time!"
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
|
res = JSON.parse(response.body)
|
||||||
|
expect(res["status"]).to eq('OK')
|
||||||
|
expect(res["successAction"]["tag"]).to eq('message')
|
||||||
|
expect(res["successAction"]["message"]).to match('Thank you')
|
||||||
|
expect(res["pr"]).to eq("lnbc50u1p3lwgknpp52g78gqya5euvzjc53fc6hkmlm2rfjhcd305tcmc0g9gaestav48sdq4gdhkven9v5sx6mmwv4ujzcqzpgxqyz5vqsp5skkz4jlqr6tkvv2g9739ygrjupc4rkqd94mc7dfpj3pgx3f6w7qs9qyyssq7mf3fzcuxlmkr9nqatcch3u8uf4gjyawe052tejz8e9fqxu4pncqk3qklt8g6ylpshg09xyjquyrgtc72vcw5cp0dzcf406apyua7dgpnfn7an")
|
||||||
|
end
|
||||||
|
|
||||||
|
context "amount too low" do
|
||||||
|
it "returns an error" do
|
||||||
|
get lnurlpay_invoice_path(address: "satoshi@kosmos.org", 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
|
||||||
|
it "returns an error" do
|
||||||
|
get lnurlpay_invoice_path(address: "satoshi@kosmos.org", 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
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET /keysend/:address/" do
|
||||||
|
it "returns a formatted Lightning Address keysend response" do
|
||||||
|
get lightning_address_keysend_path(address: "satoshi@kosmos.org")
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
|
res = JSON.parse(response.body)
|
||||||
|
expect(res["status"]).to eq('OK')
|
||||||
|
expect(res["tag"]).to eq('keysend')
|
||||||
|
expect(res["pubkey"]).to eq(Setting.lndhub_public_key)
|
||||||
|
expect(res["customData"][0]["customKey"]).to eq('696969')
|
||||||
|
expect(res["customData"][0]["customValue"]).to eq('abcdefg123456')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user