Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
pavanjoshi914 opened this issue Jun 28, 2022 · 1 comment

Comments

@pavanjoshi914
Copy link

pavanjoshi914 commented Jun 28, 2022

Abstract

Specifications such as Webln bought 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 Webln 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 Webln 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.

webln.sendPayment method

Webln SendPayment which takes paymentRequest parameter holding bolt11 invoice, 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.

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

WeblnProvider attachted by wallets currently
image

WeblnProvider attached by wallets after implementation of spec
image

Working/architecture of this spec

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

    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 = {
     "[context](http://twitter.com/context)": "[https://schema.org](https://schema.org)",
     "[type](http://twitter.com/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 as well as 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 user to download a song, once the payment is successful.

     webln.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("Webln error, check console");
          console.log('err, provider', e);
        });
    }
    

Usecases

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

@wbobeirne
Copy link
Member

Hey @pavanjoshi914, it's been a long time since you opened this and it looks like the ecosystem has carried on with metadata in payments as a concept via LNURL's LUD-06 metadata. I'm wondering if it would make more sense to just adhere to that spec for consistency, since presumably a good few wallets have started implementing payment displays using that metadata.

I definitely would have preferred something more structured like a JSON schema as you proposed, but I also don't want to add yet another spec.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants