diff --git a/CIP-0099/README.md b/CIP-0099/README.md new file mode 100644 index 0000000000..4af5c945c0 --- /dev/null +++ b/CIP-0099/README.md @@ -0,0 +1,429 @@ +--- +CIP: 99 +Title: Proof of Onboarding +Status: Active +Category: Wallets +Authors: +- Adam Dean <adam@crypto2099.io> +- Carl <vegas@hosky.io> +- Alex Dochioiu <alex@dochioiu.com> +Implementors: +- VESPR Wallet <https://www.vespr.xyz/> +- Yoroi Wallet <https://yoroi-wallet.com/> +Discussions: +- https://github.com/cardano-foundation/CIPs/pull/546 +Created: 2023-06-20 +License: CC-BY-4.0 +--- + +## 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](https://github.com/cardano-foundation/CIPs/blob/master/CIP-0013/README.md) 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: +```html +<!-- 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, a `faucet_url` and a required `code`. +* 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: +``` +```json +{ + "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 + +1. 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: +1. The project set asides some amount of budget (tokens + Lovelace [minUTxO]) for a given marketing push or IRL event +2. If desired, one or more `codes` are generated to help track and analyze claiming figures +3. QR Code(s) may be generated, printed, and otherwise displayed or given to users during the course of events +4. Users scan the code with their mobile light wallet +5. 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) +6. The project API returns a documented status code indicating the success or failure of the operation +7. 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:_ + +```html +<!-- 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: +```json +{ + "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: +```json +{ + "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: +```json +{ + "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! + +* [Version 1](https://app.swaggerhub.com/apis/CatastrophicCardano/FaucetAPI/1) + +#### Successful Responses + +##### Valid (200) + +First Successful Request + +```json +{ + "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 + +```json +{ + "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 + +```json +{ + "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 + +```json +{ + "code": 400, + "status": "invalidaddress" +} +``` + +##### Bad Request - Missing Code (400) + +No code was provided in the request + +```json +{ + "code": 400, + "status": "missingcode" +} +``` + +##### Bad Request - Invalid Network (400) + +The wallet provided is from the wrong network (testnet/mainnet) + +```json +{ + "code": 400, + "status": "invalidnetwork" +} +``` + +##### Invalid - Not Known (404) + +The specified code does not exist + +```json +{ + "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 + +```json +{ + "code": 409, + "status": "alreadyclaimed" +} +``` + +##### Invalid - Expired (410) + +For time-limited fountains, a code of 410 means that the period for redemption has expired + +```json +{ + "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 + +```json +{ + "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. + +```json +{ + "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](#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 + +- [X] Demonstrate a working MVP +- [X] Open source an MVP example of token faucet [server-side code](https://github.com/HOSKYToken/poo-genericClaim) +- [X] Receive feedback and iterate based on community feedback + +### Implementation Plan + +- [X] VESPR Mobile Wallet supports the Proof of Onboarding Protocol. +- [X] Yoroi Mobile Wallet supports the Proof of Onboarding Protocol. +- [X] HOSKY Project has released an open source server-side implementation software that may be used as a proof of concept for any interested projects. +- [X] Multiple projects at multiple, global events have successfully deployed Proof of Onboarding. +- [X] Onboard additional wallet providers, server/service providers, and redemption methods. + +## Copyright + +This CIP is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode).