Proof of Onboarding
Abstract
Since at least 2021 when Cardano entered the Mary Era and implemented Native Assets, projects and creators building on the network have sought a means to distribute their tokens efficiently to users. Of particular frustration has been the ability to onboard new users at real-world events. Solutions for this historically have been to create and preload "paper wallets" where a seed phrase and accompanying password is generated by the project, pre-populated with tokens and ADA, and then delivered over to attendees of said event.
The creation of this addendum to the CIP-13 Cardano URI scheme seeks to minimize this friction and take advantage of existing technology to enable a new era of user onboarding, particularly at real world events through the use of a defined URI scheme enabling instant and frictionless communication between a project's "token fountain" and the user's wallet to reward, incentivize, and onboard new users easier than ever.
This CIP defines an extension to the CIP-13 URI Scheme as well as an API specification to facilitate and streamline communications between wallets and project servers.
Motivation: Why is this CIP necessary?
By leveraging the power of Cardano-specific URIs (CIP-13) and the modern technological advances of mobile devices and wallets we can provide a framework for Cardano projects to attend real world events, incentivize or reward attendees via their Native Assets, and have facts and figures to help support and analyze the impact that their attendance had (Proof of Onboarding).
Specification
CIP-13 Cardano URI Extensions
Distributing Native Assets (and/or ADA) to attendees of IRL events has historically been a pain point in the ecosystem. Some implemented solutions have included: Pre-generating wallet seed phrases and pre-populating these wallets with a minimum amount of ADA as well as the desired Native Assets, (re)creating token fountain/faucet designs which can be cumbersome and not user-friendly to instruct individuals to install a wallet, visit a website, enter a code and claim tokens.
The Cardano Token Claim URI schema is proposed to allow wallets (particularly mobile wallets) to implement a QR-friendly URI structure allowing for easy onboarding and distribution of Native Assets and/or ADA to individuals in a variety of situations but not least of which being at IRL events specifically tailored and geared to onboarding new users to the ecosystem.
Examples:
<!-- Token Claim URIs -->
<a href="web+cardano://claim/v1?faucet_url=https%3A%2F%2Fclaim.hosky.io&code=consensus2023">Claim $HOSKY</a>
<a href="web+cardano://claim/v1?faucet_url=https%3A%2F%2Fclaim.hosky.io%2Fconsensus23&code=ABC123">Claim $HOSKY</a>
<a href="web+cardano://claim/v1?faucet_url=https%3A%2F%2Fclaim.nftxlv.com&code=ABC123&invoice=123456">Claim NFTxLV Commermorative NFT!</a>
ABNF Grammar
- For a token claim URI (authority =
claim
), a versioning path, afaucet_url
and a requiredcode
. - Additional query parameters may be provided and should be passed through to the provided
faucet_url
without modification.
cardanourn = "web+cardano:" claimtokenref
claimtokenref = "//claim" claimversion claimquery
claimversion = "/v1"
claimquery = ( "?" claimurl) ( "&" claimcode)
claimurl = "faucet_url=" text
claimcode = "code=" text
Token Claim URI Queries
All arguments for Token Claim URIs should be URL-encoded
Version 1 URIs
Version 1 URIs must include a faucet_url
and a code
as required parameters.
URIs may include additional arguments to suit the needs of the project's faucet API.
Handling Token Claim URI Queries
The token claim URI should consist of a required versioning path
(i.e. /v1
) as well as one or more required
or optional URL-encoded arguments.
All Token Claim URIs must include a URL-encoded faucet_url
argument as well as a code
argument.
The wallet provider should send a POST request to the provided Faucet URL
that includes:
- The change/receipt wallet address of the user
- Any additional arguments specified in the URI as key: value pairs
Example:
URI: web+cardano://claim/v1?faucet_url=https%3A%2F%2Fclaim.hosky.io%2Fconsensus23&code=ABC123
Version: 1
URL: https://claim.hosky.io/consensus23
CODE: ABC123
JSON POST Data:
{
"address": "addr1abc...xyz",
"code": "ABC123"
}
Note on the address
field
The wallet should always send the recipient address in bech32 format. If a particular token faucet implementation wishes to restrict or limit access to their faucet based on staking key or individual wallet address, this should be handled at the server end.
Supported Addresses
- Shelley-era
enterprise
address consisting of only a payment key - Shelley-era
staking
address consisting of a payment and staking key
Note on the code
field
The code is required. Specifying a code
allows for reliable tracking and/or limiting of claims to the faucet host.
Codes can be used to identify attendees of particular events (i.e. CODE = consensus2023
) or can be a unique, one-time
code per user (i.e. CODE = abc123xyz987
). In this way we leave the code to be flexible to match a variety of
analytical use cases depending upon the needs of the implementing project.
Security Considerations
- Wallets should prompt/warn users prior to sending potentially sensitive information (wallet address + code) via the
token claim URI. An informational pop-up or confirmation modal should be displayed to users such as:
We are about to send your address and code 123456 to https://claim.hosky.io. Are you sure you want to proceed?
Process Flow
The envisioned process flow for the POO Protocol is as follows:
- The project set asides some amount of budget (tokens + Lovelace [minUTxO]) for a given marketing push or IRL event
- If desired, one or more
codes
are generated to help track and analyze claiming figures - QR Code(s) may be generated, printed, and otherwise displayed or given to users during the course of events
- Users scan the code with their mobile light wallet
- The light wallet makes a POST request to the API endpoint specified in the Cardano URI containing the user's wallet address and the included code (if present)
- The project API returns a documented status code indicating the success or failure of the operation
- If a successful status is detected and returned, the project issues tokens to the specified address per their campaign settings
URI Format
The URI format consists of the CIP-13 web+cardano://
scheme, followed by the claim
authority, then a version
path.
NOTE: ALL ARGUMENTS SHOULD BE URL-ENCODED
Version 1
Version 1 URIs must include /v1
as the path of the URI.
Version 1 URIs must include two required arguments:
faucet_url
as a fully-typed URL (i.e. https://claim.hosky.io)code
as either a campaign identifier or unique, one-time use code
Version 1 URIs may include additional query parameters that should be passed through to the api server.
Version 1 Examples:
<!-- A Cardano Claim URI with campaign identifier code -->
<a href="web+cardano://claim/v1?faucet_url=https%3A%2F%2Fclaim.hosky.io&code=consensus2023">Thanks for attending Consensus 2023!</a>
<!-- A Cardano Claim URI with unique, one-time use code -->
<a href="web+cardano://claim/v1?faucet_url=https%3A%2F%2Fclaim.hosky.io&code=dff6508d8dfb4e128fd67e9ff54af147">Claim your $HOSKY now!</a>
<!-- A Cardano Claim URI with a campaign-specific code and optional user_id argument -->
<a href="web+cardano://claim/v1?faucet_url=https%3A%2F%2Fclaim.hosky.io&code=NFTxLV2023&user_id=Idjiot1337">Get your $HOSKY!</a>
Wallet Requests
Light wallets that detect and support web+cardano
URIs as well as mobile wallets who detect either a QR code or other
link with this format should parse the URI and send a POST
request to the specified URL containing a JSON payload
including:
- The user's wallet receive address
- The code
- Additional URI query parameters passed through
Examples
Faucet URL + Campaign Code
- URI:
web+cardano://claim/v1?faucet_url=https%3A%2F%2Fclaim.nftxlv.com&code=NFTxLV2023
- Faucet URL:
https://claim.nftxlv.com
- POST JSON Data:
{
"address": "addr1abc...xyz",
"code": "NFTxLV2023"
}
Faucet URL + Unique Code
- URI:
web+cardano://claim/v1?faucet_url=https%3A%2F%2Fclaim.nftxlv.com&code=NFTxLV2023
- Faucet URL:
https://claim.hosky.io
- POST JSON Data:
{
"address": "addr1abc...xyz",
"code": "ABC123"
}
Faucet URL + Campaign Code + Custom User ID
- URI:
web+cardano://claim/v1?faucet_url=https%3A%2F%2Fclaim.nftxlv.com&code=NFTxLV2023&user_id=Adam1337
- Faucet URL:
https://claim.nftxlv.com
- POST JSON Data:
{
"address": "addr1abc...xyz",
"code": "NFTxLV2023",
"user_id": "Adam1337"
}
API Server Response Codes
The API server is expected to return one of the following defined status blocks in application/json
format. Any other
responses from the API server should be considered invalid and discarded or display an error.
The expected API that any token fountain implementation should follow and wallet integrators should expect is documented on Swagger!
Successful Responses
Valid (200)
First Successful Request
{
"code": 200,
"lovelaces": "2000000",
"queue_position": 23,
"status": "accepted",
"tokens": {
"a0028f350aaabe0545fdcb56b039bfb08e4bb4d8c4d7c3c7d481c235.484f534b59": "29433292000000"
}
}
Valid Queued (201)
Subsequent Successful Request (Address + Code Match) prior to token distribution
{
"code": 201,
"lovelaces": "2000000",
"queue_position": 1,
"status": "queued",
"tokens": {
"a0028f350aaabe0545fdcb56b039bfb08e4bb4d8c4d7c3c7d481c235.484f534b59": "29433292000000"
}
}
Valid Complete (202)
Subsequent Successful Request (Address + Code Match) after token(s) are distributed
{
"code": 202,
"lovelaces": "2000000",
"status": "claimed",
"tokens": {
"a0028f350aaabe0545fdcb56b039bfb08e4bb4d8c4d7c3c7d481c235.484f534b59": "29433292000000"
},
"tx_hash": "TX1234"
}
Error Responses
Bad Request - Invalid Address (400)
The provided address is not a valid Cardano address
{
"code": 400,
"status": "invalidaddress"
}
Bad Request - Missing Code (400)
No code was provided in the request
{
"code": 400,
"status": "missingcode"
}
Bad Request - Invalid Network (400)
The wallet provided is from the wrong network (testnet/mainnet)
{
"code": 400,
"status": "invalidnetwork"
}
Invalid - Not Known (404)
The specified code does not exist
{
"code": 404,
"status": "notfound"
}
Invalid - Already Claimed (409)
An address was already used (if not code present) or the code presented was found but the address did not match
{
"code": 409,
"status": "alreadyclaimed"
}
Invalid - Expired (410)
For time-limited fountains, a code of 410 means that the period for redemption has expired
{
"code": 410,
"status": "expired"
}
Invalid - Too Early (425)
For time-limited fountains, a code of 425 means that the period for redemption has not begun yet
{
"code": 425,
"status": "tooearly"
}
Invalid - Rate Limited (429)
Rate limiting settings and details are left to the discretion and implementation of individual projects. A status code of 429 or this status response should be considered as a rate limiting response.
{
"code": 429,
"status": "ratelimited"
}
Server Error (500)
Implementations should of course be prepared to handle situations where a server is non-responsive for any reason and be prepared to handle any other, non-specified error codes including 500 codes.
Versioning & Modification Rules
If there is sufficient justification in the future for modification of this standard to the point that a "Version 2" would be necessary, those changes MUST be submitted as a new, separate CIP to this repository and follow all applicable CIP standards for acceptance. Examples of "major" changes that might justify a new version of this CIP include: fundamentally altering the URI structure, adding or removing a required field, or any other non-backwards compatible changes to the Process Flow.
Minor changes for grammar, clarity, or functionality that fall within the scope of "Version 1" of this document may be made by editing this document directly. Such changes include: grammatical or exposition changes to improve readability or clarity of communication, improvements to documented code examples, additional or optional server response information, etc.
Rationale: How does this CIP achieve its goals?
By creating a well-defined standard for both a CIP-13 URI scheme and the expected API response(s) we can create a framework that both wallets and projects can utilize to encourage and onboard new users into the ecosystem via Native Asset incentive models without needlessly and constantly reinventing the wheel for each product or project.
Furthermore, the aforementioned "paper wallet" technique has many drawbacks including:
- The person(s) responsible for generating the paper wallets at some point have access to the seed phrases generated, leading to a potential security vulnerability
- Projects would need to preload these wallets with funds/tokens; this makes it difficult and/or impossible to reliably know how many of the paper wallets were ever actually claimed
- For those wallets that go forever unclaimed, this essentially creates a permanent "burn" of both Lovelace and the native assets of the project; less than ideal
By utilizing this framework, projects can have accurate, measurable analytics into the success of various real-world marketing and event efforts: Proof of Onboarding.
Path to Active
Acceptance Criteria
- Demonstrate a working MVP
- Open source an MVP example of token faucet server-side code
- Receive feedback and iterate based on community feedback
Implementation Plan
- VESPR Mobile Wallet supports the Proof of Onboarding Protocol.
- Yoroi Mobile Wallet supports the Proof of Onboarding Protocol.
- HOSKY Project has released an open source server-side implementation software that may be used as a proof of concept for any interested projects.
- Multiple projects at multiple, global events have successfully deployed Proof of Onboarding.
- Onboard additional wallet providers, server/service providers, and redemption methods.
Copyright
This CIP is licensed under CC-BY-4.0.