minima-global / innovation-challenge

Minima Innovation Challenge Submissions
2 stars 5 forks source link

minipay - minipay #15

Open mihbor opened 2 years ago

mihbor commented 2 years ago

Before you start, please update the issue title:

Example: Minima DEX - The A Team

:pencil2: Project & Team Details

  1. MiniDapp/Project Name [required, as used in your Google Form]: Provide the name of your MiniDapp/Project - minipay

  2. MiniDapp/Project Description [optional, if changed from your application in Google Form]: Please provide a brief description of your MiniDapp/Project

  3. Team Name [optional, if changed from your application in Google Form]: Provide your team name

  4. Team Members [optional, if changed from your application in Google Form]: Please list names of all team members

:one: Phase 1 Submission

For Phase 1, please upload the following (paste the link to where you uploaded e.g. other cloud provider or GitHub (if more than 100MB) or Attach files by dragging & dropping, selecting or pasting them)

  1. A whitepaper or a pitch video with a description of the idea you have that includes: your idea, how it meets the criteria to be considered for the competition, the benefits it will bring to people and how the unique features of the Minima network can make a real difference/give an advantage to your solution.

minipay whitepaper.pdf

  1. Upload Presentation: Upload any relevant presentations/slide decks you have created

https://docs.google.com/presentation/d/1qnujdCyc8KMqzUWc7fxXH6ziqxmjAs7mkx_ek62neKI/edit?usp=sharing

minipay.pdf

:two: Phase 2 Submission

For Phase 2, please update your submission, providing the following:

  1. Code Repository Link: Provide a link to the Github URL (or other) for your MiniDapp/Project

Browser minidapp: https://github.com/mihbor/mini-payments

Android application: https://github.com/mihbor/minima-payments-nft

  1. Upload MiniDapp: If your project includes a MiniDapp, please upload your MiniDapp - this should be a .zip file using the .mds.zip extension

mini-payments.mds.zip

  1. Upload Demo: Upload any demonstration videos you have created (optional)

Demo of roadmap items 1-2) request payment over NFC (using deep-link from minidapp to Android app), scan from another phone and send: https://drive.google.com/file/d/12OvJZrxalNkGloGVAt8on7iQraIC3TV4/view?usp=sharing

Demo of roadmap item 3) establish a Layer 2 payment channel using QR code: https://drive.google.com/file/d/12OvJZrxalNkGloGVAt8on7iQraIC3TV4/view?usp=sharing

Demo of roadmap item 4) pay over existing L2 channel: https://drive.google.com/file/d/12d9k28e5lguAtpy_n5y7gJ0JZW35zXVS/view?usp=sharing

Demo of roadmap item 5) pay and request payments using NFC over existing L2 channel while offline: https://drive.google.com/file/d/11zBWYFjakKXr9f2qfoOGlWfgqWjXeXi1/view?usp=sharing

Updated presentation: https://docs.google.com/presentation/d/1rui7hP2IQ6p4fyFNkTQIgHdpwHFwaoreaGXO4K751OY/edit?usp=sharing Same, exported as pptx: minipay stage 2.pptx

:round_pushpin: Other Comments

Optional - add any other comments regarding your submission

:heavy_check_mark: Checklist

Before you post the issue:

martapiekarska commented 2 years ago

Hi Team! Can I please ask you to confirm that you are working on your final submission - the final deadline is 12th of September. Please try taking the continuous submission approach rather than send everything at once. This will help judges and show the journey you’re taking and the thought process.

mihbor commented 2 years ago

Hi @martapiekarska ,

I can report good progress.

The project is made of 2 subprojects, each in it's own repo for now. One for the browser-based minidapp, one for the native Android app.

Of the original roadmap presented in stage 1 submission: 1) pay to an address by scanning a QR code or tapping NFC (another mobile device or a pre-programmed tag). 2) request a payment to your address by presenting a QR code or your phone's NFC device or using the NFC in your phone to program an NFC tag sticker (for merchants). 3) establish a Layer 2 payment channel using QR codes or NFC and Maxima for P2P messaging. 4) pay and request payments over an existing L2 channel. 5) pay and request payments using NFC over existing L2 channel while offline. 6) payment channel route discovery via intermediaries

the progress that has been made is: 1 and 2) - Pay and Request to Pay by QR code is working in the minidapp (although the QR scanning video component doesn't working inside the MDS hub, have to click "Open in browser") and the Pay and Request to Pay by NFC (contactless) is working in the Android app. The minidapp also has a link to download the Android .apk (again, doesn't work in MDS hub, but works in browser). Once installed, you can pre-fill the Request to Pay (address, amount, token) in the minidapp and click a "deep link" that opens the Android app with the same data (address, amount, token) filled in and starts emitting via NFC.

3 and 4) payment channel works in the browser minidapp (only) as of today! :) you can create a channel, update balances (send coins) off-chain and settle the channel on-chain. The current limitations are:

These will be tackled later.

The bigger limitation and the next priority is that there is no persistence of the channel state yet. The idea is to store it using MDS sql commands and query it to display channel listing and allow to continue across browser restarts. This will also allow the Android app to read channel state and partake in the same channels as the browser minidapp.

I expect implementing persistence will be fiddly and will take some time but can be achieved in the timeframe. It is a prerequisite for 5) offline payments. Not sure if time will allow to do this but it would be a great demonstrator, IMO. To be able to transaction on a pre-existing channel between 2 parties even if without internet.

6) multi-hop payments is ambitious and certainly out of time for the PoC, but that is the route to commercialisation, as you can charge fees for using your channel and provide payment route discovery services for a fee. Another commercial opportunity is a service that checks that your counterparties are not trying to settle the channel with stale transactions while you're not looking (are offline).

I'll try to add some screenshots of what's working over the weekend.

mihbor commented 2 years ago

The minidapp in the MDS Hub:

Request view renders QR code (in MDS Hub):

Send view should show camera component but doesn't work in MDS hub (works in Chrome, via Open in Browser):

Request view renders QR code (in Chrome):

Clicking "Request on NFC" in Chrome (doesn't work in MDS Hub directly) brings up the Android app (if installed):

"Disabling reader mode" toast indicates the app starts emitting the data on NFC, rather than waiting to receive data from NFC.

Clicking Send sends the amount to the specified address (although the Send button should probably only display when NFC is in the Reader mode(!?!)):

Video recording: https://drive.google.com/file/d/12OvJZrxalNkGloGVAt8on7iQraIC3TV4/view?usp=sharing More screenshots to follow later...

mihbor commented 2 years ago

Final progress update before submission, I think. Channel persistence now works :) Updating channel over NFC also works, even offline, as intended :) :) I will post screenshots shortly and work on some kind of demo slideshow and video.

mihbor commented 2 years ago

Creating an eltoo payment channel is currently only implemented in the minidapp (not the android app) and the QR scanner works only in a browser, not embedded in the MDS HUB.

Video recording: https://drive.google.com/file/d/12OvJZrxalNkGloGVAt8on7iQraIC3TV4/view?usp=sharing

1) Pressing "Request payment channel" gets 3 public keys from Minima (trigger key, update key and settlement key) and displays them along with a QR code generated from a string concatenation thereof, separated by semicolons. It also subscribes (using websocket) to firebase updates to a transaction with the ID made of those same keys. TODO: replace firebase with maxima, an item for the roadmap

2) Pressing "Fund payment channel" on another device gets 3 public keys from Minima and opens the QR scanner to scan the public keys of the counter party. It also provides text fields where they can be manually entered (useful when testing with both sides on a development machine).

It's a current limitation of the app that only one of the parties funds the channel initially. Funding from both sides needs to be on the roadmap.

3) Once the QR code is successfully scanned, the scanner video component disappears and instead the following inputs appear:

4) Clicking "Initiate!" does a number of steps:

5) When the counter party receives a message from firebase with a new record snapshot, it does the following:

  1. When the funding party receives a message from firebase with a new record snapshot, it does the following:
    • imports the received trigger and settlement transactions which are now signed by both parties
    • Updates its channel in the DB using MDS.sql command with the exported transactions
    • Signs and posts the funding transaction
    • Starts monitoring the balance of the multisig address and coins at the eltoo address upon every NEWBLOCK message from Minima

7) When each party discovers new confirmed or unconfirmed balance at the multisig address, they update their channel status in the DB to "OPEN". They also display the follow inputs:

TODO: all transactions exchanged between parties should be checked before signing, if they meet expectations. This isn't being done currently.

mihbor commented 2 years ago

Both the minidapp and the android app have a "Channel listing" button which when clicked displays the current status and balance of channels from the DB. They also display similar options to the above:

The settlement options work the same way whether clicked in the view above (last screenshot of previous comment) or from the channel listing. Clicking "Trigger settlement" updates the channel status in the DB to "TRIGGERED" and posts the trigger transactions stored in the DB to Minima. The "Trigger settlement" button disappears. The eltoo script coins for each channel are checked upon every NEWBLOCK message from Minima. If found, their "created" block number + timelock value from the DB are compared with the current block number. Once elapsed, the "Complete settlement" button is displayed. The state value at port 99 is also checked at the eltoo script coins and if it's less the the sequence number stored in the DB, a "Post latest update" button appears. When clicked, the update transaction stored in the DB is posted to Minima and channel status in the DB updated. NB this will reset the timelock. If the timelock elapsed and the "Complete settlement" button is clicked, the settlement transaction stored in the DB is posted to Minima. TODO: a warning should be displayed if a channel is triggered and the counterparty posts an update transaction with a lower sequence number (state 99).

mihbor commented 2 years ago

Channel updates. In the minidapp if you click the "Send via channel" button, a new update+settlement transaction pair is created debiting oneself and crediting the counterparty and with an incremented sequence number (state 99). They are signed exported and send over firebase with TXN_UPDATE prefix. The receiver imports, signs and exports the transactions and updates the channel in their DB (notably the balances, exported transactions and sequence number) and sends them back over firebase with TXN_UPDATE_ACK prefix. Once the sender receives the ack, it updates it's channel in the DB (notably the balances, exported transactions, which are now signed by both parties and the sequence number) . Firebase subscriptions for all channels stored in the DB with status = "OPEN" are re-established on application startup.

In the android app only the "Request via channel" option is implemented. Once clicked, a new update+settlement transaction pair is created debiting the counterparty and crediting oneself and with an incremented sequence number. They are signed, exported, prefixed with "TXN_REQUEST" and sent to the CardService, which will emit it over NFC on request. A dialogue is displayed informing the user to press the "Request sent" button once the NFC exchange is complete. This will put the app back into "Scan" mode. When the counterparty puts their phone in NFC range and their app is in Scan mode, it will receive the transactions, import them, calculate the balance change and display a dialogue to the user to accept or reject it. Clicking "Reject" simply dismisses the dialogue screen. Clicking "Accept" will sign the transactions, export them and send them prefixed with "TXN_UPDATE_ACK" to the CardService which will emit them on request. The channel state is updated in the DB. The screen informs the user to interact via NFC again and only offers a "Finish" button, which puts the app back into "Scan" mode. When the requesting party puts their phone back in NFC range, it receives and imports the update and settlement transactions, which are now signed by both parties. It updates the channel in its DB and brings back the default screen. This doesn't firebase or anything like that, only NFC, so the interaction can take place even offline. Settlement of course will require internet connection

Video of an offline eltoo transaction over a pre-existing channel: https://drive.google.com/file/d/11zBWYFjakKXr9f2qfoOGlWfgqWjXeXi1/view?usp=sharing

mihbor commented 2 years ago

Notes of project design: Currently project is composed of 2 separate git repositories. The minidapp is located at: https://github.com/mihbor/mini-payments and the Android application at: https://github.com/mihbor/minima-payments-nft

TODO: merge these into one Kotlin multiplatform project.

The minidapp is using Kotlin/JS with Compose for Web as the UI framework and the Android app is using Kotlin/Android with Jetpack Compose as the UI framework.

minidapp project source layout:

Android project source layout:

Database schema for storing channel state:

CREATE TABLE IF NOT EXISTS channel(
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
    status VARCHAR,
    my_balance DECIMAL(20,10),
    other_balance DECIMAL(20,10),
    my_address VARCHAR,
    other_address VARCHAR,
    my_trigger_key VARCHAR,
    my_update_key VARCHAR,
    my_settle_key VARCHAR,
    other_trigger_key VARCHAR,
    other_update_key VARCHAR,
    other_settle_key VARCHAR,
    sequence_number INT,
    time_lock INT,
    trigger_tx VARCHAR,
    update_tx VARCHAR,
    settle_tx VARCHAR,
    multisig_address VARCHAR,
    eltoo_address VARCHAR
);

Sorry, no UML diagrams :P