BitcoinAndLightningLayerSpecs / WebBTC

10 stars 1 forks source link

Spec-Proposal: Extend WebBTC SendPayment method to pass metadata as a optional parameter. #19

Open pavanjoshi914 opened 2 years ago

pavanjoshi914 commented 2 years ago

Abstract

Specifications such as WebBTC bring better solutions to the UX for lightning networks. On top of this, many broad applications such as instant payments via a web browser using Bitcoin Sats (eg. Alby), tippings for content writers, podcasts and streamers (Medium tipping via Alby) and many more came into working. Along with every transaction we can also store additional information in form of metadata which can make specifications such as WebBTC and more broad and applicative in terms of interactivity.

Transaction lists as we know them from our private bank accounts are often a simple list of transactions sorted by date. Each transaction has data like Sender, Receiver, amount, reason and date.

The aim of this proposal is to extend existing standards such as WebBTC to enrich transactions with additional information as structured metadata so that transactions containing static data contain more meaningful information giving more interactivity to the transactions.

window.webbtc.sendPayment method

WebBTC SendPayment which takes invoice as a string, we can extend this function to add an extra "optional" parameter named metadata which will hold metadata as a string which can be passed to the Wallets.

window.webbtc.sendPayment(paymentRequest: string, metadata?: string): Promise<SendPaymentResponse>;

WebBtc Provider attachted by wallets currently image

WebBTC Provider attached by wallets after implementation of spec image

Working/architecture of this spec

  1. Make a Request to Wallet for WebBTC Provider Via Triggering SendPayment()

    window.webbtc.sendPayment(paymentRequest: string, metadata?: string): Promise<SendPaymentResponse>;

  2. Structure Metadata and pass it to the wallet in Callback

    Use Schema.org specifications to structure metadata in form of JSON-LD.

    eg.

    var Metadata = {};
    Metadata = {
     "type": "AudioObject",
     "name": "title",
     "creator": "artist",
     "image": "image" 
     }
     export var Metadata;

    Learn more about how to structure metadata for Bitcoin Transactions Visit — Here.

  3. Validate Metadata

    Metadata is user-generated, such type of metadata should be cross-checked for its correctness and before performing any further action we have to do validation of metadata.

    What is JSON Schema? 🧐

    JSON Schema is a JSON media type for defining the structure of JSON data. JSON Schema provides a contract for what JSON data is required for a given application and how to interact with it.

    Schemas can be created to validate received data against a predefined data model. To do this many validator plugins are available too

    • Generate Schema

    • Compile Schema

    • Validate received data for that particular schema

    Zod plugin can be used to validate JSON schemas and Object schemas. The best thing about this plugin is that it has zero external dependencies involved.

    Validator function which validates schemas using Zod plugin

    • Schema Created using Zod plugin
    
    import { z } from "zod";
    
    export const audioObjectSchema = z.object({
      type: z.string(),
      name: z.string().optional(),
      creator: z.string().optional(),
      image: z.string().optional(),
    });
    • Validator function to validate metadata
    
    import { audioObjectSchema } from "./audioObjectSchema";
    
    export function isBase64(str: string) {
      if (str === "" || str.trim() === "") {
        return false;
      }
      try {
        return btoa(atob(str)) == str;
      } catch (err) {
        return false;
      }
    }
    
    export function MetadataValidator(metadata: { [key: string]: string }) {
      let hasValidType = false;
      let hasValidImage = true;
      for (const key in metadata) {
        if (key == "type") {
          if (metadata[key] == "AudioObject") {
            const parsed = audioObjectSchema.safeParse(metadata);
            if (parsed.success) {
              hasValidType = true;
            }
          }
        }
        if (key == "image") {
          hasValidImage = isBase64(metadata[key]);
        }
      }
    
    return hasValidType && hasValidImage;
    }
    • To Validate Metadata Just call the function by passing metadata.
    const isMetadataValid = MetadataValidator(metadata);
  4. Render Metadata in Confirmation Dialogue (If Valid) 🚦

    If metadata is successfully validated, we can show the user the amount the user will be paying along with the content used will be buying in form of metadata.

    Here users can see the purpose of the transaction, looking over the content, the user will be buying through this transaction and will have a clear idea of everything before making the payment.

  5. Store, Interact and do after actions with Metadata 💾

    Once the user confirms his/her payment and the transaction gets successful -

    • In Bitcoin Lightning Wallet

    We can store and render the metadata in the transaction database of the wallet allowing users to interact with the metadata.

    • In Lightning Application

    Once the payment is successful, we can allow the user to access his purchased content such as allowing the user to download a song, once the payment is successful.

     webbtc.sendPayment(Bolt 11 invoice, Metadata)
              .then(function(r) {
                // required to protect metadata while paying empty invoices
                if(r != undefined){  
                // do after payment actions with the metadata. eg. allowing user to download song after payment is done 
              }
              })
              .catch(function(e) {
                alert("Failed: " + e.message);
                console.log('err pay:', e);
              });
        })
        .catch(function(e) {
          alert("Webbtc error, check console");
          console.log('err, provider', e);
        });
    }

Usecases build on top of webln specification

To get a better grasp on the proposal idea I decided to create a simple prototype through which a visitor can play a song if they like they can buy a song. While purchasing a song during confirmation payment they get to know about the song name, artist, and song image(send as base64 encoded string, decode on Alby side). After successful payment, a song gets downloaded into users' local storage.

Video Link

Prototype Code

Alby with extended webln specification

gr0kchain commented 2 years ago

Very nice use case indeed! What are your thoughts about extracting the metadata from the files themselves however, in this case the Mp3Tag metadata for the file? Not sure if the WebBTC spec should be handling this as it seems to be a separate concern.

Although there doesn't seem to be harm in provisioning this extra metadata field, but that would require wallets to implement parsing it when they might obtain this information in different ways.

Some HTTP responses might even include this using the HEAD method. I see a benefit here in standardising presenting this information, but it can be abstracted into various unrelated specifications to WebBTC. Just some thoughts.

pavanjoshi914 commented 2 years ago
  1. depending on the use case needed, this can be handled by wallet itself as a functionality. It currently focuses on creating a spec, creating standards for what can be passed as metadata and creating standard schemas on the wallet side so that it can be followed universally. here is the schema for the AudioObject and its supported attributes https://schema.org/AudioObject

  2. We use schema.org specification to provide standards for the passing of metadata, users can prepare metadata according to the documentation, written on WebBtC specs. pass the metadata on the wallet side. as per changes defined by these specs, the wallet can do similar changes, and handle metadata so that there are no multiple ways wallets can use by following the standards we create

  3. True we thought about this, but including it in a particular specification such as WebBTC or webln rather than web-based API's makes it more flexible and allows more space to make changes according to the standards community needs

gr0kchain commented 2 years ago

JSON Schema is a good choice imho considering the web nature. Let's keep this open for a bit to see if we get more engagement. Good suggestion BTW

pavanjoshi914 commented 2 years ago

JSON Schema is a good choice imho considering the web nature. Let's keep this open for a bit to see if we get more engagement. Good suggestion BTW

For sure! if this is approved , we can start with the PR

thebells1111 commented 2 years ago

Maybe the JSON schema could be similar to a TLV record so existing schemas could be used with both the keysend method and the sendPayment method. Here's and example of TLV record schemas, with Podcasting 2.0 using 7629169 record.

https://github.com/satoshisstream/satoshis.stream/blob/main/TLV_registry.md