LUD-06
Zapにおいて
プロフィール欄の lud06
の入力欄(別名称のことも)が用意されている場合があります。
技術的に言うと、
lud06
はプロフィール(
kind:0
)のJSONに含められるフィールドの一つです(
NIP-57参照)。
LNURLにおいて
nostrのZap(
NIP-57)はこのLUD-06に基づいています。
LUD-06の一連の処理の流れの中でnostrのZap関連の処理を追加で行う形です。
仕様
> 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..."}
(訳注)他の仕様で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\"]]"
4. ライトニングウォレット
は、ユーザが支払う正確な金額を指定できる支払いダイアログを表示する。次の制約に縛られる:
最大の送金可能金額 = min(maxSendable, どれだけウォレットから支払えるかというローカルな見積もり)
最小の送金可能金額 = max(minSendable, ウォレットが許可する最小金額)
加えて、支払いダイアログは次を含まなければならない:
LNURL
クエリ文字列から抽出したドメイン名
text/plain
形式で送信されたメタデータを表示する手段
次を含んでも良い
image/png
または image/jpeg
の内容を含むimage要素
5. ライトニングウォレット
は、GETリクエストを送る
<callback><?|&>amount=<milliSatoshi>
amount
はユーザが指定した金額でmillisatoshi単位。
6. ライトニングサービス
はGETリクエストを受け取り、以下の形式のJSONレスポンスを返す:
_.json{
pr: string, // bech32でシリアライズされたライトニングインボイス
routes: [] // から配列
}
または
{"status":"ERROR", "reason":"error details..."}
7. ライトニングウォレット
は提供されたインボイス内の h
タグが metadata
文字列をUTF-8エンコーディングでバイト列にしたもののハッシュ値と一致することを検証する
8. ライトニングウォレット
は提供されたインボイス内の金額がユーザが先ほど指定した金額と等しいことを検証する
9. ライトニングウォレット
はインボイスに対して支払う。この時点で追加でユーザへの確認を行う必要はない。
サーバサイドのLNURL-PAYのためのmetadataについての注意事項
クライアントからの最初の呼び出し時
metadataオブジェクトを組み立てて、JSONに変換し、文字列として親のJSONに含める。
クライアントから2回目の呼び出し時
1. 次の通りハッシュを計算する: sha256(utf8ByteArray(エスケープされていないmetadata文字列))
2. 得られたハッシュ値を用いて、支払いリクエストを生成する