Skip to content

Commit

Permalink
value spec - add "auto" as a payment action
Browse files Browse the repository at this point in the history
  • Loading branch information
daveajones committed Apr 25, 2023
1 parent 60b02f8 commit f526d1e
Show file tree
Hide file tree
Showing 2 changed files with 423 additions and 321 deletions.
274 changes: 155 additions & 119 deletions value/blip-0010.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# bLIP 10
# bLIP 10 - A TLV record for lightning payments to carry podcast payment metadata

```text
Original Author: Satoshis Stream <[email protected]>
Expand All @@ -8,18 +8,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.
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.

Example:

```json
{
"podcast": "PODCASTNAME",
"feedID": 1337,
"episode": "EPISODENAME",
"action": "boost",
"ts": 33
"podcast": "PODCASTNAME",
"feedID": 1337,
"episode": "EPISODENAME",
"action": "boost",
"ts": 33
}
```

Expand All @@ -29,22 +35,39 @@ 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 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.

### 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 keysend payment. 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:

```json
{"app_name": "Castamatic", "app_version": "8.0.6", "value_msat_total": 49960, "url": "https://feeds.buzzsprout.com/1844352.rss", "podcast": "Mere Mortals", "action": "stream", "episode": "The Art Of NFT's & Aimless Wandering", "episode_guid": "Buzzsprout-9931017", "value_msat": 97940, "ts": 574, "name": "Podcaster", "sender_name": "Peter"}
{
"app_name": "Castamatic",
"app_version": "8.0.6",
"value_msat_total": 49960,
"url": "https://feeds.buzzsprout.com/1844352.rss",
"podcast": "Mere Mortals",
"action": "stream",
"episode": "The Art Of NFT's & Aimless Wandering",
"episode_guid": "Buzzsprout-9931017",
"value_msat": 97940,
"ts": 574,
"name": "Podcaster",
"sender_name": "Peter"
}
```

Treated as `utf8`, the hex value of this json record would be:
`7b226170705f6e616d65223a202243617374616d61746963222c20226170705f76657273696f6e223a2022382e302e36222c202276616c75655f6d7361745f746f74616c223a2034393936302c202275726c223a202268747470733a2f2f66656564732e62757a7a7370726f75742e636f6d2f313834343335322e727373222c2022706f6463617374223a20224d657265204d6f7274616c73222c2022616374696f6e223a202273747265616d222c2022657069736f6465223a202254686520417274204f66204e4654277320262041696d6c6573732057616e646572696e67222c2022657069736f64655f67756964223a202242757a7a7370726f75742d39393331303137222c202276616c75655f6d736174223a2039373934302c20227473223a203537342c20226e616d65223a2022506f64636173746572222c202273656e6465725f6e616d65223a20225065746572227d0a`

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.
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.

### Fields

Expand All @@ -53,9 +76,11 @@ Identifying the podcast **required**: use any of `podcast`, `guid`, `feedID` and
* `podcast` (str) Title of the podcast
* `feedID` (int) ID of podcast in PodcastIndex.org
* `url` (str) RSS feed URL of podcast
* `guid` (str) [The `<podcast:guid>` tag](https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#guid).
* `guid` (
str) [The `<podcast:guid>` 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**
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
Expand All @@ -75,15 +100,25 @@ Rest of keys:
* `message` (str) Text message to add to the boost message: a boostagram
* `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.
* `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.)
* `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.)


## Actions

* `boost`


## Reference Implementations

* Breez: <https://github.com/breez/breezmobile/blob/4cf057c066d03c155964f0c4db43476cd70a57ab/lib/bloc/podcast_payments/podcast_payments_bloc.dart>
* Podverse: <https://github.com/podverse/podverse-shared/blob/fff84c0143dea4fa01241109b8666d4c0b9a6ffc/src/satoshiStream.ts>
*
Breez: <https://github.com/breez/breezmobile/blob/4cf057c066d03c155964f0c4db43476cd70a57ab/lib/bloc/podcast_payments/podcast_payments_bloc.dart>
*
Podverse: <https://github.com/podverse/podverse-shared/blob/fff84c0143dea4fa01241109b8666d4c0b9a6ffc/src/satoshiStream.ts>
* PodStation: <https://github.com/podStation/podStation/pull/249>
* Helipad: <https://github.com/Podcastindex-org/helipad/blob/203e72dafb65e4f9e89540fbe4fc07a456a9907a/src/main.rs>
* Rust-V4V: <https://github.com/Conshax/Rust-V4V/blob/master/src/boostagram.rs>
Expand All @@ -98,40 +133,40 @@ Podverse cuts the episode name short and `stream` actions are sent as `streaming

```json
{
"podcast": "Test Podcast Anchor",
"feedID": 6015671,
"episode": "this is a very very very very very very very very very very ",
"episode_guid": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"ts": 24,
"action": "boost",
"speed": "1",
"pubkey": "podverse-pubkey",
"value_msat_total": 100000,
"uuid": "75758d19-c4af-4da2-80ce-a5c84a0f1642",
"app_name": "Podverse",
"name": "Alby Test User PUT",
"sender_name": "Alwin_Conshax",
"message": "test"
"podcast": "Test Podcast Anchor",
"feedID": 6015671,
"episode": "this is a very very very very very very very very very very ",
"episode_guid": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"ts": 24,
"action": "boost",
"speed": "1",
"pubkey": "podverse-pubkey",
"value_msat_total": 100000,
"uuid": "75758d19-c4af-4da2-80ce-a5c84a0f1642",
"app_name": "Podverse",
"name": "Alby Test User PUT",
"sender_name": "Alwin_Conshax",
"message": "test"
}
```

#### Stream

```json
{
"podcast": "Test Podcast Anchor",
"feedID": 6015671,
"episode": "this is a very very very very very very very very very very ",
"episode_guid": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"ts": 315,
"action": "streaming",
"speed": "1",
"pubkey": "podverse-pubkey",
"value_msat_total": 100000,
"uuid": "654072b5-9825-4792-b502-31ee9f1ec6aa",
"app_name": "Podverse",
"name": "Alby Test User PUT",
"sender_name": "Alwin_Conshax"
"podcast": "Test Podcast Anchor",
"feedID": 6015671,
"episode": "this is a very very very very very very very very very very ",
"episode_guid": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"ts": 315,
"action": "streaming",
"speed": "1",
"pubkey": "podverse-pubkey",
"value_msat_total": 100000,
"uuid": "654072b5-9825-4792-b502-31ee9f1ec6aa",
"app_name": "Podverse",
"name": "Alby Test User PUT",
"sender_name": "Alwin_Conshax"
}
```

Expand All @@ -143,39 +178,39 @@ Castamatic sends `value_msat_total` only on boosts not on streams.

```json
{
"message": "test",
"app_name": "Castamatic",
"app_version": "8.6.0",
"value_msat_total": 100000,
"url": "https://anchor.fm/s/da6b03c0/podcast/rss",
"podcast": "Test Podcast Anchor",
"action": "boost",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"episode_guid": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"feedID": 6015671,
"value_msat": 95049,
"ts": 0,
"name": "Alby Test User PUT",
"sender_name": "Alwin_Conshax"
"message": "test",
"app_name": "Castamatic",
"app_version": "8.6.0",
"value_msat_total": 100000,
"url": "https://anchor.fm/s/da6b03c0/podcast/rss",
"podcast": "Test Podcast Anchor",
"action": "boost",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"episode_guid": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"feedID": 6015671,
"value_msat": 95049,
"ts": 0,
"name": "Alby Test User PUT",
"sender_name": "Alwin_Conshax"
}
```

#### Stream

```json
{
"app_name": "Castamatic",
"app_version": "8.6.0",
"url": "https://anchor.fm/s/da6b03c0/podcast/rss",
"podcast": "Test Podcast Anchor",
"action": "stream",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"episode_guid": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"feedID": 6015671,
"value_msat": 50940,
"ts": 254,
"name": "Test User Peppe the first",
"sender_name": "Alwin_Conshax"
"app_name": "Castamatic",
"app_version": "8.6.0",
"url": "https://anchor.fm/s/da6b03c0/podcast/rss",
"podcast": "Test Podcast Anchor",
"action": "stream",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"episode_guid": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"feedID": 6015671,
"value_msat": 50940,
"ts": 254,
"name": "Test User Peppe the first",
"sender_name": "Alwin_Conshax"
}
```

Expand All @@ -187,63 +222,64 @@ Fountain sends the itemID as a string, not an int.

```json
{
"app_name": "Fountain",
"value_msat_total": 100000,
"name": "Alby Test User PUT",
"podcast": "Test Podcast Anchor",
"feedID": 6015671,
"action": "boost",
"sender_id": "nSiq7id78JAdH9uY1pIy",
"sender_name": "@alwin_conshax",
"message": "test",
"itemID": "14934154309",
"boost_link": "https://fountain.fm/episode/14934154309",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"ts": 15,
"time": "00:00:15"
"app_name": "Fountain",
"value_msat_total": 100000,
"name": "Alby Test User PUT",
"podcast": "Test Podcast Anchor",
"feedID": 6015671,
"action": "boost",
"sender_id": "nSiq7id78JAdH9uY1pIy",
"sender_name": "@alwin_conshax",
"message": "test",
"itemID": "14934154309",
"boost_link": "https://fountain.fm/episode/14934154309",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"ts": 15,
"time": "00:00:15"
}
```

#### Stream

```json
{
"app_name": "Fountain",
"value_msat_total": 50000,
"name": "Alby Test User PUT",
"podcast": "Test Podcast Anchor",
"feedID": 6015671,
"action": "stream",
"sender_id": "pqwMfFdkCwtj8LKm0tNu",
"sender_name": "@moritz_conshax",
"message": null,
"itemID": "14934154309",
"boost_link": "https://fountain.fm/episode/14934154309",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"ts": 62,
"time": "00:01:02"
"app_name": "Fountain",
"value_msat_total": 50000,
"name": "Alby Test User PUT",
"podcast": "Test Podcast Anchor",
"feedID": 6015671,
"action": "stream",
"sender_id": "pqwMfFdkCwtj8LKm0tNu",
"sender_name": "@moritz_conshax",
"message": null,
"itemID": "14934154309",
"boost_link": "https://fountain.fm/episode/14934154309",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"ts": 62,
"time": "00:01:02"
}
```

### Breez

Breez sends the guid on the itemID field and the sender_name is an empty string on streams.
Besides that Breez takes its fee from the total instead on top of the total as fountain does, this results in the received value of a split being less than it should calculated from the total.
Besides that Breez takes its fee from the total instead on top of the total as fountain does, this results in the
received value of a split being less than it should calculated from the total.

#### Boost

```json
{
"podcast": "Test Podcast Anchor",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"action": "boost",
"time": "00:00:24",
"feedID": 6015671,
"itemID": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"app_name": "Breez",
"value_msat_total": 100000,
"sender_name": "Jade Monkey",
"message": "test"
"podcast": "Test Podcast Anchor",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"action": "boost",
"time": "00:00:24",
"feedID": 6015671,
"itemID": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"app_name": "Breez",
"value_msat_total": 100000,
"sender_name": "Jade Monkey",
"message": "test"
}

```
Expand All @@ -252,14 +288,14 @@ Besides that Breez takes its fee from the total instead on top of the total as f

```json
{
"podcast": "Test Podcast Anchor",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"action": "stream",
"time": "00:02:37",
"feedID": 6015671,
"itemID": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"app_name": "Breez",
"value_msat_total": 100000,
"sender_name": ""
"podcast": "Test Podcast Anchor",
"episode": "this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long episode name!!!",
"action": "stream",
"time": "00:02:37",
"feedID": 6015671,
"itemID": "12b4df54-af38-4c53-8099-82f9caacdcd5",
"app_name": "Breez",
"value_msat_total": 100000,
"sender_name": ""
}
```
Loading

0 comments on commit f526d1e

Please sign in to comment.