- Author: @aslesarenko, @MrStahlfelge
- Status: Proposed
- Created: 18-August-2021
- Updated: 31-October-2022
- License: CC0
- Forking: not needed
- Description
- Background And Motivation
- ErgoPay Interaction Protocol
- Data Formats
- Implementation in Wallet apps
- Implementation in dApp
- Benefits for dApps
- Benefits for Wallets
- Optional enhancements
This EIP defines a standard for cross-platform interaction between an online dApp and a wallet app for creating, signing and sending Ergo transactions.
Cryptocurrency wallets, (like Ergo Android Wallet) typically support scanning QR codes of Payment Request (on mobile devices) or intercepting a link with a special URI scheme. After parsing a payment request the wallet can build a new transaction, sign it using a secret key stored locally on the device and then send to the blockchain.
However, in general, this only can be done for simple transactions like transferring ERGs and assets between Pay-To-Public-Key addresses or transactions which only spend boxes from P2PK addresses.
The reason for this is simple. In Ergo's eUTXO model a box can be protected by an arbitrarily complex contract (aka spending condition) and any spending transaction should satisfy that condition by adding required context variables, creating expected number of outputs with specific registers depending on the contract. There is no way for a universal wallet application to know all the specific details of all the possible contracts.
On the contrary, every Ergo dApp (think of website) is usually built on top of specific contracts. Business logic of the dApp includes spending of the boxes protected by those application-specific contracts. In other words, any dApp is in full control of creating transactions and thus can spend its own contracts without above mentioned problems. However, the dApp cannot sign those transactions, because signing requires knowledge of private keys which are not stored on the dApp, but instead stored on the wallet app.
Thus, interaction between a dApp and a wallet is required such that:
- the dApp builds a transaction and makes it available for the wallet application
- wallet app shows a confirmation screen to the user, displaying the inboxes and outboxes it is going to sign
- when user confirms, wallet app signs the transaction and submits it to the blockchain or returns back to the dApp
- dApp monitors the transaction on the blockchain and upon confirmations proceeds with its business logic.
One possible implementation of such an interaction scheme is described in EIP-0012. It, however, only suitable for in-browser wallets, which can interact with dApps via javascript code injected into a web context.
Luckily, the design of Ergo contracts allows for a simple and universal implementation suitable for mobile or desktop wallets. This EIP describes the interaction protocol and the reference implementation.
In this 3 step process the main question is: "How the transaction built in dApp can be transferred to the wallet application so that it can be signed there?".
An ErgoPay interaction between Wallet, and dApp is driven by dApp's user and proceeds as the following:
-
The user enters the necessary information in the dApp's UI and proceeds to a payment screen. Optionally, dApp can request user's P2PK address with an extra step using a signing request with a placeholder URL (see below).
-
The payment screen shows transaction details and a QR code as well as a clickable link.
-
User clicks the link to hand the information over to a wallet application on the same device, or scans the QR code using a wallet application.
-
The Hot Wallet application parses the QR code data and obtains either
ErgoPaySigningRequest
orReducedTransaction
data (see Data Formats section). In the former case the QR code data contains an url to downloadErgoPaySigningRequest
from the dApp. -
When
ErgoPaySigningRequest
orReducedTransaction
is obtained, it is shown as a payment screen on the wallet app containing the same transaction details as the dApp screen. -
The user compares the dApp's screen, the Wallet's screen and the transaction details and confirms the payment by using a "Sign" button. If the Hot Wallet also supports EIP-0019 and private keys are not available, then the sign button behaves like a "Cold Sign" button according to EIP-0019.
-
The wallet application signs the transaction either using local private keys or using Cold Wallet and EIP-0019 protocol. The result of signing is
SignedTransaction
data. -
The Hot Wallet obtains the transaction id and sends it to the dApp using
ErgoPayTransactionSent
API post message toreplyTo
url if it is provided, if successful the wallet then submitsSignedTransaction
to the blockchain. If the url is not provided, then the wallet submits the transaction to blockchain without notifying the dApp. The dApp can monitor the blockchain by txId which it can learn from UnsignedTransaction. This is based on the fact thatUnsignedTransaction.id == SignedTransaction.id
holds for all transactions. -
dApp monitors the transaction by id and proceeds with its business logic upon receiving enough confirmations. This concludes the ErgoPay protocol.
Additional requirements:
- many instances of ErgoPay protocol MUST be able to run simultaneously within the dApp
- the Hot Wallet MAY implement "one-at-a-time" signing. When the signing is interrupted for some reason it can be started from the step 3) (i.e. scanning the QR)
- when dApp receives the transaction id, but the
SignedTransaction
is not accepted to the blockchain then the dApp SHOULD detect this situation and stop monitoring that transaction.
The data formats of this EIP are based on a new binary data structure and
serialization format called ReducedTransaction
which is described in
EIP-0019.
Below we describe the data formats specified by this EIP and refer to the formats defined in EIP-0019.
Wallet apps should be able to initiate ErgoPay both by using URI schemes (clickable links) or QR codes.
Option 1: dApp providing URL request to fetch ErgoPaySigningRequest information from (Dynamic request)
ergopay://<URL>
URL is provided without the https prefix. http communication is not allowed except for IP addresses (in order to test within a local network).
The provided URL can contain a #P2PK_ADDRESS#
placeholder. The wallet application will replace this
placeholder with an actual P2PK address.
Examples:
ergopay://sigmausd.io/signingRequest/2001-16b8-66c4-b800-6e52-8ce4
will make the wallet app requesthttps://sigmausd.io/signingRequest/2001-16b8-66c4-b800-6e52-8ce4
ergopay://192.168.0.1/html
will make the wallet app requesthttp://192.168.0.1/html
ergopay://auctionhouse.org/bid/#P2PK_ADDRESS#
will make the wallet app requesthttps://auctionhouse.org/bid/3Wx7Z8FywaL4ofunDCV1NaTJX5CpjTubMrjpCkEhnNBAgJLGfRcD
The wallet application should request URL and obtain the following data (json format)
ErgoPaySigningRequest:
- reducedTx: ReducedTransaction (optional*)
- address: String (optional)
- message: String (optional*)
- messageSeverity: String (optional) "INFORMATION", "WARNING", "ERROR"
- replyTo: String (optional)
Either a transaction or a message must be provided, otherwise the request is invalid.
The wallet application should show the message and display the messageSeverity in a suitable way, if provided.
If transaction details are obtained, a payment screen opens for the user to confirm signing the transaction. Transaction details CAN BE OPTIONALLY shown on the payment screen of the wallet application.
If address is provided by the dApp, the wallet can preselect the key the user needs to sign the transaction.
After signing is performed and the SignedTransaction
data is obtained, the
wallet can POST the following data to the dApp using url in replyTo field from the
signing request (json format) if it is provided.
ErgoPayTransactionId:
- txId: String
dApps should not rely on this request to be made. It could happen that the transaction was submitted to a node, but the reply couldn't be executed. dApps know the transaction id and should monitor the mempool and blockchain on their own.
In case no transaction was provided, the wallet app displays the message that should inform the user about further steps needed.
When dapp does not need to use an extra request, the ReducedTransaction
could
also be encoded in the QR code or link:
ergopay:<ReducedTransaction, base 64 url safe encoded>
It is not possible to provide description, address, message and replyTo url in this simpler interchange format.
dApp developers should keep in mind that there are length restrictions for URI schemes and QR codes. Both should be able handle up to 2900 chars, but QR codes with a lot of content need to be shown bigger to be read without problems.
We recommend to use an URL request if the payload exceeds 400 chars.
Ergo Wallet App 1.6 or higher https://github.com/ergoplatform/ergo-wallet-app
- ErgoPay showcase example https://github.com/MrStahlfelge/ergopay-server-example
- Ergoplatform Jackson Serialization Library https://github.com/MrStahlfelge/ergoplatform-jackson
- TokenJay https://tokenjay.app
- Mosaik tutorial https://docs.ergoplatform.com/dev/stack/mosaik/intro/
- Spectrum DEX
- ergopad
ErgoPay provides a fast, easy, and secure way for users to buy goods and services in a dApp or on a website. When supported, ErgoPay can substantially increase checkout conversion rates, user loyalty and purchase frequency, and reduced checkout time.
- dApp or website don’t need to handle user's secrets (mnemonic/private keys). Instead, once the user has signed the transaction to confirm purchase intent, your app or website receives a transaction id to monitor payment status on the blockchain.
- dApp's users don't need to worry about security of their private keys as the wallet app guarantees they never leave the device
- ErgoPay EIP is compatible with Cold Wallet EIP, thus users can use Cold Wallet devices to sign transaction within ErgoPay signing process.
- adding ErgoPay to product detail pages, the cart, checkout page, in payment settings, or anywhere else a user can choose ErgoPay as the payment method or initiate a purchase.
- The payment screen can be presented immediately after the user taps the Ergo Pay button, without any interim screens or pop-ups except to prompt for necessary product details, such as size or quantity.
- ErgoPay is simple and universal. It supports all smart contracts and offers the flexibility to implement simple to complex dApps.
Any wallet application team should consider supporting ErgoPay in their wallet along with basic wallet features. Users can participate in Ergo dApps and wallet team can receive service fees from those transactions.
The following optional enhancements to the protocol may be supported by wallet applications and dApps. All of these enhancements are backwards compatible and fall back to the behaviour and data formats described above when not used.
Wallet applications announce supporting a certain optional enhancement by setting a specific
HTTP header when fetching ErgoPaySigningRequest
. If the dApp supports this feature as well, it can
use it by changing the data formats as described in the paragraphs below.
The original ErgoPay protocol can only transfer one reduced transaction at a time, thus if a user needs to sign multiple transactions at once it needs multiple steps. To make it more convenient to sign multiple transactions, especially useful for chained transactions, the described ErgoPay enhancements supports transferring multiple transactions at once.
HTTP header to indicate support: ErgoPay-MultipleTx: supported
If a wallet app sets this HTTP header field, the ErgoPaySigningRequest
might contain a
reducedTxList
array field instead of the reducedTx
field. All other fields stay the same.
The ErgoPaySigningRequest
must not contain reducedTx
and reducedTxList
fields simultaneously.
The transactions are signed. If an error occurs during signing, no transaction will be submitted.
Signed transactions are submitted to Ergo network in their order in the reducedTxList
array. If
an error occurs during submitting, no further transactions will be submitted.
In case reducedTxList
array field and replyToUrl
field is set, the data POSTed to this url is an
array of successfully submitted transaction id strings, if at least one transaction was submitted
successfully:
ErgoPayTransactionIds:
- txIds: [String]
dApps should not rely on this data to be posted and should not expect all transactions to be submitted. There is always the possibility of a connection or other failure leading to only some of the transactions being submitted. It is only guaranteed that the transactions are submitted in the correct order.
The original ErgoPay protocol only defines that dApps can set a single address to sign with in the
ErgoPaySigningRequest
. It could be necessary that a transaction needs to be signed by multiple
of the user's addresses.
HTTP header sent by wallet app to indicate support: ErgoPay-CanSelectMultipleAddresses: supported
If a wallet app sets this HTTP header field, the ErgoPaySigningRequest
might contain an
addresses
array field instead of the address
field. All other fields stay the same.
The ErgoPaySigningRequest
must not contain address
and addresses
fields simultaneously.
A dynamic ErgoPay request's URL can contain a special #P2PK_ADDRESS#
placeholder.
The wallet application will fill this address with an address the user could choose before the dApp
is connected. This can be used to connect wallets to dApps or to set an address to use one time.
It could be necessary for the dApp to know about multiple derived addresses. To remain
compatible to dApps that can only process a single address, the placeholder #P2PK_ADDRESS#
to
trigger a user to choose a single or multiple addresses should stay the same. If a user selects
multiple addresses to use with the dApp, fetching the ErgoPaySigningRequest
is changed in the
following way:
- instead of a GET request, a POST request is done
- the
#P2PK_ADDRESS#
placeholder is replaced with the constant keyword "multiple" - the POST request contains a json array with the selected addresses
Because this won't work with dApps not supporting selecting multiple addresses, the wallet
application has to check if the dApp is supporting the feature before letting the users select
multiple addresses. This pre-check is a POST request to the URL with the #P2PK_ADDRESS#
placeholder replaced by the keyword "multiple_check". If this request is successful (2xx return
code), users can select multiple addresses.
Example:
the ErgoPay URL ergopay://auctionhouse.org/bid/#P2PK_ADDRESS#
will make a wallet supporting
choosing multiple addresses make a POST request with empty body to
https://auctionhouse.org/bid/multiple_check
first. This request can be
a) successful (2xx return code) or
b) fail (3xx-5xx return code)
For b), the user will get an address selection screen to choose a single address from that is used
to replace the #P2PK_ADDRESS#
placeholder to fetch the ErgoPaySigningRequest
. If the user selects
"address0", a request to https://auctionhouse.org/bid/address0
is done.
For a), the user will get an address selection screen to choose multiple addresses from. The user
can select a1) multiple addresses address1, address2, ... or a2) a single address address1.
For a2), the single address is used to replace the #P2PK_ADDRESS#
placeholder to fetch the
ErgoPaySigningRequest
. A GET request to https://auctionhouse.org/bid/address0
is done.
For a1), a POST request to https://auctionhouse.org/bid/multiple
is done with the body being a
list of the selected addresses: ["address1", "address2", ...]