diff --git a/value/blip-0010.md b/value/blip-0010.md index d6ee94d..a8aa9ed 100644 --- a/value/blip-0010.md +++ b/value/blip-0010.md @@ -6,45 +6,48 @@ Created: 2022-01-24 License: CC0 ``` -## Abstract +
-Using Value 4 Value apps, listeners can send sats to the hosts of the podcasts they listen to. Per minute sending is -called `stream` and manual payments are called `boost`s. If there is a message to the podcaster, with a boost, it is -called a `boostagram`. -These apps (see [Reference Implementations](#reference-implementations)) adopted bLIP 10 with the **7629169** TLV type -for inputting key-value JSON metadata about the sent payment. The TLV holds data about the timestamp when the payment -was sent within the episode, the name of the podcast and -its [Guid](https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#guid), among other fields -described in the [Specification](#specification) section. +## Purpose -Example: +Using Value 4 Value apps, listeners can send sats to the podcasts they listen to. A per-minute payment is +called a `stream`, a manually triggered payment is called a `boost` and an automatically recurring (i.e. scheduled) +payment is called an `auto` payment. If there is a message to the podcaster included in a `boost` it is referred to as +a `boostagram`. + +The payload is a simple JSON structure that is encoded as a TLV in the Lightning payment when it is sent. This +structure is explained in this document. + + +Simple Example: ```json { - "podcast": "PODCASTNAME", - "feedID": 1337, - "episode": "EPISODENAME", + "podcast": "Podcasting 2.0", + "feedID": 920666, + "episode": "Episode 127: Fortress of Freedom", "action": "boost", "ts": 33 } ``` -## Copyright - -This bLIP is licensed under the CC0 license. +
## Specification -The sender of the payments (the podcast app) needs to input some metadata so the podcast host can identify whom the -payment is for. Most fields are optional. +The sender of a bLIP-10 payment (i.e. - the podcast app) needs to include some metadata so the podcast host can +identify for whom the payment is for. Most fields are optional. + +
### Formatting and encoding -A flat key-value json structure is used where the keys listed below can be set. The json string is then encoded -into `utf8` and attached to the keysend payment. Receivers of messages must be aware that there is no guarantee for the -order of the keys. +A flat, key-value json structure is used where the keys listed below can be set. The json string is then encoded +into `utf8` and attached to the Lightning payment. Most of the time, the payment will be a `keysend` payment, but this +TLV data can be used in standard BOLT11 and BOLT12 payments also. Receivers of messages must be aware that there +is no guarantee for the order of the keys. -Sample JSON string, containing a selection of keys: +A more complex example: ```json { @@ -63,62 +66,104 @@ Sample JSON string, containing a selection of keys: } ``` -Treated as `utf8`, the hex value of this json record would be: -`7b226170705f6e616d65223a202243617374616d61746963222c20226170705f76657273696f6e223a2022382e302e36222c202276616c75655f6d7361745f746f74616c223a2034393936302c202275726c223a202268747470733a2f2f66656564732e62757a7a7370726f75742e636f6d2f313834343335322e727373222c2022706f6463617374223a20224d657265204d6f7274616c73222c2022616374696f6e223a202273747265616d222c2022657069736f6465223a202254686520417274204f66204e4654277320262041696d6c6573732057616e646572696e67222c2022657069736f64655f67756964223a202242757a7a7370726f75742d39393331303137222c202276616c75655f6d736174223a2039373934302c20227473223a203537342c20226e616d65223a2022506f64636173746572222c202273656e6465725f6e616d65223a20225065746572227d0a` +Treated as `utf-8`, the hex value of the above json record would be: +```base64 +7b226170705f6e616d65223a202243617374616d61746963222c20226170705f76657273696f6e223a2022382e302e36222c202276616c75655f +6d7361745f746f74616c223a2034393936302c202275726c223a202268747470733a2f2f66656564732e62757a7a7370726f75742e636f6d2f31 +3834343335322e727373222c2022706f6463617374223a20224d657265204d6f7274616c73222c2022616374696f6e223a202273747265616d22 +2c2022657069736f6465223a202254686520417274204f66204e4654277320262041696d6c6573732057616e646572696e67222c202265706973 +6f64655f67756964223a202242757a7a7370726f75742d39393331303137222c202276616c75655f6d736174223a2039373934302c2022747322 +3a203537342c20226e616d65223a2022506f64636173746572222c202273656e6465725f6e616d65223a20225065746572227d0a +``` -If a field is indicated to be a `str` in the fields-list, that means it is a JSON string (within quotes) and `int`s are -plain numbers. +
+ +### Types + +If a field is indicated to be a `str` in the fields-list, that means it is a JSON string (within quotes). An `int` is +a plain number. + +
### Fields -Identifying the podcast **required**: use any of `podcast`, `guid`, `feedID` and/or `url`. **guid preferred** +Identifying the podcast **required**: use one or more of `podcast`, `guid`, `feedID` and/or `url`. **guid preferred** +* `guid` (str) [The `` tag](https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#guid). * `podcast` (str) Title of the podcast -* `feedID` (int) ID of podcast in PodcastIndex.org +* `feedID` (int) ID of podcast in PodcastIndex.org directory * `url` (str) RSS feed URL of podcast -* `guid` ( - str) [The `` tag](https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#guid). + +
Identifying the episode **recommended**: use any of `episode`, `itemID` and/or `episode_guid`. **episode_guid preferred** -* `episode` (str) Episode of the podcast -* `itemID` (int) ID of episode in PodcastIndex.org +* `episode` (str) Title of the podcast episode +* `itemID` (int) ID of episode in PodcastIndex.org directory * `episode_guid` (str) The GUID of the episode -Information about time within the episode **recommended**: use any of `ts`, `time`. **ts preferred** +
-* `ts` (int) Timestamp when the boost/stream was sent WITHIN the episode, in seconds (playback position) -* `time` (str) HH:MM:SS timestamp when the boost/stream was sent WITHIN the episode (playback position) +Information about time within the episode **recommended**: use one of `ts` or `time`. **ts preferred** -Rest of keys: +* `ts` (int) Timestamp of when the payment was sent, in seconds, as an offset from zero (i.e. - playback position) +* `time` (str) Timestamp of when the payment was sent, in HH:MM:SS notation, as an offset from 00:00:00 + (i.e. - playback position) -* `action` **recommended**: (str) "boost", "stream" or "auto" +
+ +Other fields that are strongly recommended: + +* `action` **recommended**: (str) "boost", "stream" or "auto". See Appending B of the + [value](/value.md#appendix-b---payment-actions) spec for details. * `app_name`: **recommended** (str) Name of sending app +* `sender_name` **recommended** (str) Name of the sender (free text, not validated in any way) +* `value_msat_total`: **recommended** (int) TOTAL Number of millisats for the payment before any fees are subtracted. + This should be the number the listener entered into the app. Preserving + this value is important for numerology reasons. Certain numeric values can + have significance to the sender and/or receiver, so giving a way to show + this is critical. + +
+ +Other optional fields: + +* `message` (str) Text message to add to the payment. When this field is present, the payment is known as a + "boostagram". * `app_version`: (str) Version of sending app -* `boost_link`: (str) App specific URL containing route to podcast, episode, and/or timestamp at time of the action -* `message` (str) Text message to add to the boost message: a boostagram +* `boost_link`: (str) App specific URL containing route to podcast, episode, and/or timestamp at time of the action. + The use case for this is sending a link along with the payment that will take the recipient to + the exact playback position within the episode where the payment was sent. * `name` (str) Name for this split in value tag -* `sender_name` **recommended** (str) Name of sender (free text, not checked by signatures) * `sender_id` (str) Static random identifier for users, not displayed by apps to prevent abuse. Apps can set this - per-feed or app-wide. A GUID-like random identifier or a hash works well. Max 32 ascii characters. -* `speed` (str) Speed in which the podcast was played, in decimal. So 0.5 is half speed and 2 is double speed. -* `uuid` (str) Unique UUID of the payment -* `value_msat_total`: **recommended** (int) TOTAL Number of millisats for the payment (all splits together, before fees. - The actual number someone entered in their player, for numerology purposes.) + per-feed or app-wide. A GUID-like random identifier or a hash works well. Max 32 bytes (64 ascii + characters). This can be a Nostr hex encoded pubkey (not NIP-19) for purposes of sender attribution. +* `signature` (str) Optionally, this field can contain a signature for the payment, to be able to verify that the + user who sent it is actually who they claim in the `sender_id` field. If the `sender_id` contains + a Nostr public key, this field should contain a Nostr `sig` value as a 64-byte encoded hex string. + For the purpose of generating the Nostr signature, the following data should be serialized: + [0,`sender_id`,`ts`,1,[],`message`] to conform to the + [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md) specification. The resulting + serialized string should be hashed with `sha256` to obtain the value. +* `speed` (str) Speed in which the podcast was playing, in decimal notation at the time the payment was sent. So 0.5 + is half speed and 2 is double speed. +* `uuid` (str) Unique UUID of the payment. -## Actions - -* `boost` +
## Reference Implementations * + Breez: + * + Podverse: + * PodStation: * Helipad: * Rust-V4V: