feat(cli): add --payer-data to amy offer request

Offers can be configured (via nmanage / ShockWallet) to require payer
fields; Lightning.Pub rejects requests missing them with the misleading
"Invalid Offer" (code 1) reply. A flag to attach payer_data makes such
offers testable from the CLI.

https://claude.ai/code/session_01Fh7MRv8477pJiAJZ7yF87r
This commit is contained in:
Claude
2026-06-12 15:18:45 +00:00
parent b37e62cd62
commit 18c21ad51b
2 changed files with 15 additions and 5 deletions
+1 -1
View File
@@ -249,7 +249,7 @@ $ amy relay publish-lists # broadcast updated kind:10002/10050/10051
| Command | What it does |
|---|---|
| `amy offer info NOFFER` | Decode a `noffer1…` pointer (pubkey, relays, price type/amount). Local, no network. |
| `amy offer request NOFFER [--amount SATS] [--timeout MS]` | kind:21001 round-trip: publish the request to the pointer's relays and print the returned BOLT11. `--amount` is required for spontaneous offers; fixed offers default to the pointer's price. |
| `amy offer request NOFFER [--amount SATS] [--timeout MS] [--payer-data K=V,…]` | kind:21001 round-trip: publish the request to the pointer's relays and print the returned BOLT11. `--amount` is required for spontaneous offers; fixed offers default to the pointer's price. `--payer-data` attaches payer fields (e.g. `email=a@b.c`) for offers that require them — Lightning.Pub answers "Invalid Offer" (code 1) when they are missing. |
### CLINK Debits
@@ -39,9 +39,10 @@ import com.vitorpamplona.quartz.nip05DnsIdentifiers.Nip05Id
*
* - `info <noffer>` decodes a pointer locally (no network).
* - `discover <nip05>` resolves a profile's advertised offer from its NIP-05 `.well-known`.
* - `request <noffer> [--amount N] [--timeout MS] [--follow]` runs the kind-21001 round-trip:
* publishes the request to the pointer's relays and prints the returned BOLT-11. With
* `--follow` it chases an "Expired or Moved" (code 3) reply to the `latest` pointer.
* - `request <noffer> [--amount N] [--timeout MS] [--follow] [--payer-data k=v,…]` runs the
* kind-21001 round-trip: publishes the request to the pointer's relays and prints the
* returned BOLT-11. With `--follow` it chases an "Expired or Moved" (code 3) reply to the
* `latest` pointer. `--payer-data` attaches the payer fields some offers require.
* - `pay <noffer> --with <ndebit> [--amount N]` fetches the invoice and settles it end-to-end
* through a CLINK debit pointer (offer round-trip → debit round-trip).
*
@@ -137,6 +138,15 @@ object OfferCommands {
val amount = args.flag("amount")?.toLongOrNull()
val timeoutMs = args.longFlag("timeout", 15_000)
val follow = args.bool("follow")
// Offers can be configured to require payer fields (e.g. email); Lightning.Pub
// rejects a request missing them as "Invalid Offer" (code 1), so the round-trip
// is untestable against such offers without a way to attach them.
val payerData: Map<String, Any?>? =
args.flag("payer-data")?.split(',')?.associate { pair ->
val idx = pair.indexOf('=')
if (idx <= 0) return Output.error("bad_args", "--payer-data expects key=value[,key2=value2…]")
pair.take(idx) to pair.substring(idx + 1)
}
var offer =
ClinkPointerParser.parse(args.positional(0, "noffer").trim()) as? NOffer
@@ -151,7 +161,7 @@ object OfferCommands {
if (relays.isEmpty()) return Output.error("bad_pointer", "noffer carries no relay to reach")
val client = OfferClient(offer, ctx.signer)
val requestEvent = client.requestInvoice(amountSats = amount)
val requestEvent = client.requestInvoice(amountSats = amount, payerData = payerData)
val reply = ctx.requestResponse(requestEvent, relays, client.responseFilter(requestEvent.id), timeoutMs)
if (reply == null) {