generated at
LUD-06

Zapにおいて
プロフィール欄の lud06 の入力欄(別名称のことも)が用意されている場合があります。
ここに入力するのはLNURLアドレスです。LNURLアドレスを載せることでZapを受け取れるようになります。

技術的に言うと、 lud06 はプロフィール( kind:0 )のJSONに含められるフィールドの一つです(NIP-57参照)。

LNURLにおいて
LNURLの仕様(LUD)の内、LNURL-payの仕様の一番基本となる仕様です。

nostrのZap(NIP-57)はこのLUD-06に基づいています。
LUD-06の一連の処理の流れの中でnostrのZap関連の処理を追加で行う形です。

hr
仕様

NIP-57#6451dbee2b3130000063acf0のシーケンス図を見ると、やりとりの流れを掴めるでしょう。
インボイス受領後の流れは、ライトニングインボイス#64603f5d0b84ec000009c1f5の図を参照してください。

> LUD-06: payRequest の基本仕様

これは、ウォレットで静的なQRコードをスキャンするか、静的なLNURLアドレスをクリックして、期待した支払いの詳細情報を得ることができるようにするアイデアである。詳細情報には通常のライトニングインボイスに比べて幅広いメタデータを含められる。そして、金額は固定であっても、決められた範囲の間であってもよい。

ユーザが支払いの条件を承諾(および、所定の金額が決まっていなければ金額を決定)したら、ウォレットはサービスを呼び出し、ライトニングインボイス明細(BOLT-11)を取得する。明細にはメタデータのハッシュ値 h タグ (description_hash) が含まれており、期待する金額とハッシュ値に一致した場合には、インボイスに対する支払いを続行する。

静的なQR/NFC/リンクへの支払い
1. ユーザは ライトニングウォレット でLNURL QRコードをスキャンするか、 lighting:LNURL.. 形式のリンクをペーストもしくは共有すると、 ライトニングウォレット はLNURLをデコードする
(注釈) LNURL... 形式のリンクの仕様はlud01を参照
2. ライトニングウォレット は、デコードしたLNURLを用いて ライトニングサービス に対してGETリクエストを送る
3. ライトニングウォレット は、 ライトニングサービス から次の形式のJSONレスポンスを受け取る:
_.json
{ "callback": string, // payリクエストのパラメータを受け付ける、ライトニングサービスのURL。 "maxSendable": number, // ライトニングサービスが受け取っても構わない最大の金額(millisatoshi) "minSendable": number, // ライトニングサービスが受け取っても構わない最小の金額(millisatoshi) // 1以上、`maxSendable`以下である必要がある。 "metadata": string, // メタデータのJSON。ここでは生の文字列として表現されなければならず、 // 後のシグニチャの検証ステップに渡す必要がある。 "tag": "payRequest" // LNURLの種別 }
もしくは
_.json
{"status": "ERROR", "reason": "error details..."}
(訳注) metadata の検証は効果が小さく冗長であると指摘され、検証処理の削除が検討されています
(訳注)他の仕様でJSONレスポンスの追加の項目が定められています。
LUD-12では支払い時のコメントを指定できるように commentAllowed が定義されています。
NIP-57では allowsNostr nostrPubkey が定義されています。
metadata JSONは配列であり、一つの text/plain エントリを含まなければならない。他の種類のエントリは全て任意である。メタデータJSON配列は、 image/png;base64 image/jpeg;base64 のいずれかを含むか、いずれも含まないようにしなければならない。
metadata JSON配列に含められるのは配列に限られる。 metadata 配列内の配列の最初の要素は、常にメタデータの種類を表す文字列であり、以降の要素はどんなJSON型であってもよい。実装はそれが常に文字列型であると仮定してはならない(MUST NOT)。
_.json
[ [ "text/plain", // 必須 string // 支払い時および取引履歴(transaction log)内に表示される短い説明 ], [ "text/long-desc", // 任意 string // 支払いについてのより長い説明。改行を含んでも良い(MAY) ], [ "image/png;base64", string // Base64 文字列(任意)。リストやグリッド内でこのLNURLを表すための512 x 512ピクセルのPNGサムネイル。最大136536文字(Base64エンコードで100KBに相当する画像データ) ], [ "image/jpeg;base64", // optional string // Base64 文字列(任意)。リストやグリッド内でこのLNURLを表すための512 x 512ピクセルのJPEGサムネイル。最大136536文字(Base64エンコードで100KBに相当する画像データ) ], // 将来のためのエントリ [ string, any ] ]
そして、これは文字列として送信される
_.json
"[[\"text/plain\", \"lorem ipsum blah blah\"]]"
(注釈)ライトニングアドレス(LUD-16)では、 text/identifier エントリを定義している
4. ライトニングウォレット は、ユーザが支払う正確な金額を指定できる支払いダイアログを表示する。次の制約に縛られる:
最大の送金可能金額 = min(maxSendable, どれだけウォレットから支払えるかというローカルな見積もり)
最小の送金可能金額 = max(minSendable, ウォレットが許可する最小金額)
加えて、支払いダイアログは次を含まなければならない:
LNURL クエリ文字列から抽出したドメイン名
text/plain 形式で送信されたメタデータを表示する手段
次を含んでも良い
image/png または image/jpeg の内容を含むimage要素
5. ライトニングウォレット は、GETリクエストを送る
<callback><?|&>amount=<milliSatoshi>
amount はユーザが指定した金額でmillisatoshi単位。
(注釈) NIP-57では、これらに加えて nostr (Zapリクエスト)と lnurl を送るように定めている→NIP-57#646050e32b313000005be09f
6. ライトニングサービス はGETリクエストを受け取り、以下の形式のJSONレスポンスを返す:
_.json
{ pr: string, // bech32でシリアライズされたライトニングインボイス routes: [] // から配列 }
または
{"status":"ERROR", "reason":"error details..."}
(注釈) pr BOLT-11形式のライトニングインボイス
7. ライトニングウォレット は提供されたインボイス内の h タグが metadata 文字列をUTF-8エンコーディングでバイト列にしたもののハッシュ値と一致することを検証する
(注釈)ハッシュ値はSHA-256。BOLT-11仕様を参照のこと。
(注釈)NIP-57では、 metadata の代わりに Zapリクエスト のハッシュ値を含める NIP-57#6451ea5d2b3130000063ad0e
8. ライトニングウォレット は提供されたインボイス内の金額がユーザが先ほど指定した金額と等しいことを検証する
9. ライトニングウォレット はインボイスに対して支払う。この時点で追加でユーザへの確認を行う必要はない。

サーバサイドのLNURL-PAYのためのmetadataについての注意事項
クライアントからの最初の呼び出し時
metadataオブジェクトを組み立てて、JSONに変換し、文字列として親のJSONに含める。

クライアントから2回目の呼び出し時
1. 次の通りハッシュを計算する: sha256(utf8ByteArray(エスケープされていないmetadata文字列))
2. 得られたハッシュ値を用いて、支払いリクエストを生成する