From 655bf5eee002b0b71658926f0ba8e14656c95709 Mon Sep 17 00:00:00 2001 From: "Robert C. Martin" Date: Fri, 19 May 2023 08:39:27 -0500 Subject: [PATCH] lud06 zapping works. --- spec/more_speech/nostr/zaps_spec.clj | 47 ++++++++-------- src/more_speech/nostr/zaps.clj | 84 +++++++++++++++------------- 2 files changed, 67 insertions(+), 64 deletions(-) diff --git a/spec/more_speech/nostr/zaps_spec.clj b/spec/more_speech/nostr/zaps_spec.clj index 33737ee..282613c 100644 --- a/spec/more_speech/nostr/zaps_spec.clj +++ b/spec/more_speech/nostr/zaps_spec.clj @@ -23,47 +23,44 @@ (context "zap address" (context "zap address is in tag" (it "determines lud16 zap address from zap tag" - (let [event {:tags [[:zap "zap-address" "lud16"]]}] - (should= "zap-address" (zaps/get-zap-address event)))) + (let [event {:tags [[:zap "me@you.xxx" "lud16"]]}] + (should= "https://you.xxx/.well-known/lnurlp/me" + (zaps/get-lnurl event)))) - (it "rejects zap address when there are conflicting zap tags" - (let [event {:tags [[:zap "zap-address" "lud16"] - [:zap "zap-address-1" "lud16"]]}] - (should-throw Exception "conflicting zaps" - (zaps/get-zap-address event)))) + (it "passes mistyped address" + (let [event {:tags [[:zap "zap-address" "xxx"]]}] + (should= "zap-address" (zaps/get-lnurl event)))) - (it "accepts multiple zap tags that don't conflict" - (let [event {:tags [[:zap "zap-address-1" "lud16"] - [:zap "zap-address-1" "lud16"]]}] - (should= "zap-address-1" (zaps/get-zap-address event)))) - - (it "only accepts lud16" - (let [event {:tags [[:zap "zap-address" "lud06"]]}] - (should-throw Exception "lud06 unimplemented" - (zaps/get-zap-address event)))) - - (it "assumes an unspecified address type is lud16" + (it "passes untyped address" (let [event {:tags [[:zap "zap-address"]]}] - (should= "zap-address" (zaps/get-zap-address event)))) + (should= "zap-address" (zaps/get-lnurl event)))) ) (context "No zap tag" (it "rejects if no profile for author" (let [event {:pubkey 1}] (should-throw Exception "no zap tag or profile" - (zaps/get-zap-address event)))) + (zaps/get-lnurl event)))) (it "rejects if profile has no lud16" (let [event {:pubkey 1}] (gateway/add-profile @db 1 {:name "somebody"}) - (should-throw Exception "no lud16 in profile" - (zaps/get-zap-address event)))) + (should-throw Exception "no zap tag or profile" + (zaps/get-lnurl event)))) - (it "gets zap addr from profile" + (it "gets lud16 zap addr from profile" (let [event {:pubkey 1}] (gateway/add-profile @db 1 {:name "somebody" - :lud16 "zap-addr"}) - (should= "zap-addr" (zaps/get-zap-address event)))) + :lud16 "me@you.xxx"}) + (should= "https://you.xxx/.well-known/lnurlp/me" + (zaps/get-lnurl event)))) + + (it "gets lud06 zap addr from profile" + (let [event {:pubkey 1} + lnurl (bech32/encode-str "lnurl" "the-lnurl")] + (gateway/add-profile @db 1 {:name "somebody" + :lud06 lnurl}) + (should= "the-lnurl" (zaps/get-lnurl event)))) ) (context "lud16 parsing" diff --git a/src/more_speech/nostr/zaps.clj b/src/more_speech/nostr/zaps.clj index 0b7bcad..a9d150c 100644 --- a/src/more_speech/nostr/zaps.clj +++ b/src/more_speech/nostr/zaps.clj @@ -18,43 +18,6 @@ (:use (seesaw [core])) (:import (java.net URLEncoder))) -(defn get-zap-address-from-tag [event] - (let [zap-tags (events/get-tag event :zap) - [zap-addr lud-type :as zap-tag] (first zap-tags) - lud-type (if (some? lud-type) lud-type "lud16")] - (cond - (empty? zap-tags) - nil - - (not= "lud16" lud-type) - (throw (Exception. (str lud-type " unimplemented"))) - - (not (every? #(= zap-tag %) zap-tags)) - (throw (Exception. "conflicting zaps")) - - :else - zap-addr))) - -(defn get-zap-address-from-profile [event] - (let [author-id (:pubkey event) - profile (gateway/get-profile (get-db) author-id) - zap-addr (:lud16 profile)] - (cond - (nil? profile) - (throw (Exception. "no zap tag or profile")) - - (nil? zap-addr) - (throw (Exception. "no lud16 in profile")) - - :else - zap-addr))) - -(defn get-zap-address [event] - (let [zap-address (get-zap-address-from-tag event)] - (if (some? zap-address) - zap-address - (get-zap-address-from-profile event)))) - (defn parse-lud16 [lud16] (let [lud16 (.toLowerCase lud16) match (re-matches config/lud16-pattern lud16)] @@ -67,6 +30,50 @@ (let [[name domain] (parse-lud16 lud16)] (str "https://" domain "/.well-known/lnurlp/" name))) +(defn- decode-lnurl [lnurl] + (try + (bech32/address->str lnurl) + (catch Exception e + (log-pr 1 'decode-lnurl (.getMessage e) lnurl)))) + +(defn get-lnurl-from-tag [event] + (let [zap-tags (events/get-tag event :zap) + [zap-addr lud-type] (first zap-tags)] + (cond + (empty? zap-tags) + nil + + (= "lud16" lud-type) + (lud16->lnurl zap-addr) + + (= "lud06" lud-type) + (decode-lnurl zap-addr) + + :else + zap-addr))) + +(defn get-lnurl-from-profile [event] + (let [author-id (:pubkey event) + profile (gateway/get-profile (get-db) author-id) + lud16 (:lud16 profile) + lud06 (:lud06 profile)] + (cond + (some? lud16) + (lud16->lnurl lud16) + + (some? lud06) + (decode-lnurl lud06) + + :else + (throw (Exception. "no zap tag or profile")) + ))) + +(defn get-lnurl [event] + (let [zap-address (get-lnurl-from-tag event)] + (if (some? zap-address) + zap-address + (get-lnurl-from-profile event)))) + (defn make-zap-request [wallet-response event amount comment lnurl] (let [{:strs [maxSendable minSendable commentAllowed allowsNostr]} wallet-response @@ -118,8 +125,7 @@ (defn zap-author [event _e] (try - (let [zap-address (get-zap-address event) - lnurl (lud16->lnurl zap-address) + (let [lnurl (get-lnurl event) ln-response (client/get lnurl) wallet-response (json/read-str (:body ln-response)) {:strs [callback status reason]} wallet-response]