Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: use kind 8905 and tags
  • Loading branch information
ATXMJ committed Nov 17, 2025
commit 0f59aa5ba42d50bb46d6baba4a228da5a284f56e
79 changes: 62 additions & 17 deletions A3.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## payto: Payment Targets (RFC-8905)

### Event Kind

This NIP defines `kind:8905` for payment target events. This kind is **replaceable** and **parameterized-replaceable** using the `"d"` tag to identify different contexts (e.g., `"profile"` for user payment targets).

Events of this kind MUST include a `"d"` tag with a parameter that identifies the context of the payment targets.

`draft` `optional` `author:atxmj`

This NIP standardizes the approach to payment and tip invocations from user profiles, posts, chats, and elsewhere using the [RFC-8905 (payto:) URI scheme](https://www.rfc-editor.org/rfc/rfc8905.html) standard for "payment targets".
Expand All @@ -17,10 +23,26 @@ Similar to these, NIP-A3 provides a standardized payment target framework rather

### payto: event broadcasting

Clients *may* allow users to specify a list (one or many) of "payment targets" as specified in the [RFC-8905 (payto:) URI scheme](https://www.rfc-editor.org/rfc/rfc8905.html) standard, each consisting of a pair of values, `type` and `authority` (to be labeled as preferred by the client), in order to generate an event of kind `0` (`set_metadata`) specifying "payment targets" that *may* be used for payment or tip invocation from a user's profile, posts, chats, or elsewhere.
Clients *may* allow users to specify a list (one or many) of "payment targets" as specified in the [RFC-8905 (payto:) URI scheme](https://www.rfc-editor.org/rfc/rfc8905.html) standard, each consisting of a pair of values, `type` and `authority` (to be labeled as preferred by the client), in order to generate an event of kind `8905` (`payto`) with a `"d"` tag parameter of `"profile"` and `payto` tags specifying "payment targets" that *may* be used for payment or tip invocation from a user's profile, posts, chats, or elsewhere.

The client *may* allow the user to input and perform validation on the `type` and `authority` fields (labeled as preferred by the client) as they see fit.

#### Tag Format

Payment targets are specified using `payto` tags with the following structure:

```text
["payto", "<type>", "<authority>", "<optional_extra_1>", "<optional_extra_2>", ...]
```

Where:
- The first element is always the literal string `"payto"`
- The second element is the payment `type` (e.g., `"bitcoin"`, `"lightning"`)
- The third element is the `authority` (e.g., address, username)
- Additional elements are optional and reserved for future RFC-8905 features

Clients **must** understand elements 0–2; they **may ignore** any additional elements for forward compatibility.

#### Validation Guidelines

Following RFC-8905 guidelines, clients should validate payto entries as follows:
Expand All @@ -40,8 +62,14 @@ The client then broadcasts an event such as
```json
{
"pubkey": "afc93622eb4d79c0fb75e56e0c14553f7214b0a466abeba14cb38968c6755e6a",
"kind": 0,
"content": "{\"payto\": [{\"type\": \"bitcoin\", \"authority\": \"bc1qxq66e0t8d7ugdecwnmv58e90tpry23nc84pg9k\"}, {\"type\": \"nano\", \"authority\": \"nano_1dctqbmqxfppo9pswbm6kg9d4s4mbraqn8i4m7ob9gnzz91aurmuho48jx3c\"}, {\"type\": \"unknowntype\", \"authority\": \"l7tbta5b9xze6ckkfc99uohzxd009b0r\"}]}"
"kind": 8905,
"content": "",
"tags": [
["d", "profile"],
["payto", "bitcoin", "bc1qxq66e0t8d7ugdecwnmv58e90tpry23nc84pg9k"],
["payto", "nano", "nano_1dctqbmqxfppo9pswbm6kg9d4s4mbraqn8i4m7ob9gnzz91aurmuho48jx3c"],
["payto", "unknowntype", "l7tbta5b9xze6ckkfc99uohzxd009b0r"]
],
...
}
```
Expand Down Expand Up @@ -73,9 +101,9 @@ This is a list of recommended payment target types for clients to recognize and

### payto: event observation

On observation of events of kind `0` (`set_metadata`), the event *may* specify the key `"payto"` with a value consisting of a list (one or many) of "payment target" values, each specified as a pair of values `type` and `authority` as specified in the [RFC-8905 (payto:) URI scheme](https://www.rfc-editor.org/rfc/rfc8905.html) for payment targets.
On observation of events of kind `8905` (`payto`) with a `"d"` tag parameter of `"profile"`, the event *may* include `payto` tags, each specifying a "payment target" with values `type` and `authority` as specified in the [RFC-8905 (payto:) URI scheme](https://www.rfc-editor.org/rfc/rfc8905.html) for payment targets.

For each pair of values in the `payto` list, the client *should* assemble a full `payto://` deep link URI and render it as a button or link in the user's profile, posts, chats, or elsewhere, in the format of `payto://<type>/<authority>`.
For each `payto` tag where the first element is `"payto"`, the second element is the `type`, and the third element is the `authority`, the client *should* assemble a full `payto://` deep link URI and render it as a button or link in the user's profile, posts, chats, or elsewhere, in the format of `payto://<type>/<authority>`.

The client *should* store a map of [recognized payment target types](#recommended-payment-target-types) along with a corresponding icon & stylization configuration (to be defined by the client).

Expand All @@ -92,8 +120,14 @@ If a client sees an event like this:
```json
{
"pubkey": "afc93622eb4d79c0fb75e56e0c14553f7214b0a466abeba14cb38968c6755e6a",
"kind": 0,
"content": "{\"payto\": [{\"type\": \"bitcoin\", \"authority\": \"bc1qxq66e0t8d7ugdecwnmv58e90tpry23nc84pg9k\"}, {\"type\": \"nano\", \"authority\": \"nano_1dctqbmqxfppo9pswbm6kg9d4s4mbraqn8i4m7ob9gnzz91aurmuho48jx3c\"}, {\"type\": \"unknowntype\", \"authority\": \"l7tbta5b9xze6ckkfc99uohzxd009b0r\"}]}"
"kind": 8905,
"content": "",
"tags": [
["d", "profile"],
["payto", "bitcoin", "bc1qxq66e0t8d7ugdecwnmv58e90tpry23nc84pg9k"],
["payto", "nano", "nano_1dctqbmqxfppo9pswbm6kg9d4s4mbraqn8i4m7ob9gnzz91aurmuho48jx3c"],
["payto", "unknowntype", "l7tbta5b9xze6ckkfc99uohzxd009b0r"]
],
...
}
```
Expand All @@ -110,9 +144,9 @@ The client chooses to ignore the third *unrecognized* `type`, and only embeds th

#### Example of steps taken by the client on observation

- for each pair of `type` and `authority` values in the `payto` list
- *optionally* do some minimal validation on those fields in a generalized way that applies to any payment type, and filter out invalid pairs
- *optionally* filter out any pairs with an [*unrecognized*](#recommended-payment-target-types) `type`
- for each `payto` tag in the event (where the first element equals `"payto"`)
- *optionally* do some minimal validation on the `type` (second element) and `authority` (third element) fields in a generalized way that applies to any payment type, and filter out invalid tags
- *optionally* filter out any tags with an [*unrecognized*](#recommended-payment-target-types) `type`
- assemble a full `payto://` deep link URI in the format `payto://<type>/<authority>`
- render a button, link, or dropdown in user profiles, posts, chats, and elsewhere using the assembled deep links and the corresponding icons & stylization configurations for *recognized* `type` values

Expand All @@ -122,20 +156,31 @@ The client chooses to ignore the third *unrecognized* `type`, and only embeds th

Clients implementing both NIP-A3 and NIP-57 may choose to use `payto` lightning entries as an alternative or complement to the `lud16` field for zap functionality:

- When zapping a user, clients can check for `payto` entries with `type: "lightning"` in their kind 0 metadata
- When zapping a user, clients can check for `payto` tags with `type: "lightning"` in their kind 8905 payto events
- These can be used alongside or instead of `lud16` fields for Lightning Network payments
- The `authority` field for lightning entries should contain a Lightning address (e.g., `[email protected]`) or a direct LNURL
- Clients should prioritize user preferences but may fall back between `lud16`, `payto` lightning entries, and `zap` tags on events

Example of a profile supporting both approaches:

```json
{
"kind": 0,
"content": "{\"lud16\":\"[email protected]\",\"payto\":[{\"type\":\"lightning\",\"authority\":\"[email protected]\"},{\"type\":\"bitcoin\",\"authority\":\"bc1q...\"}]}",
"pubkey": "...",
// ...
}
[
{
"kind": 0,
"content": "{\"lud16\":\"[email protected]\"}",
"pubkey": "..."
},
{
"kind": 8905,
"content": "",
"tags": [
["d", "profile"],
["payto", "lightning", "[email protected]"],
["payto", "bitcoin", "bc1q..."]
],
"pubkey": "..."
}
]
```

This provides redundancy and allows users to specify multiple payment methods while maintaining compatibility with existing zap implementations.