diff --git a/README.md b/README.md index 53cbf58..14ed0a1 100644 --- a/README.md +++ b/README.md @@ -41,12 +41,12 @@ Pi.authenticate(scopes, onIncompletePaymentFound).then(function(auth) { }); ``` -### Request a payment +### Request a payment (User-To-App) The `createPayment` method enables you to request a payment from the current user to your app's account. The user will be prompted with a modal provided by the Pi Wallet, enabling them to sign the -transaction and submit it to the Pi blockchain. +transaction and submit it to the Pi Blockchain. ```javascript @@ -67,14 +67,21 @@ Pi.createPayment({ ``` -This code block is a **simplified example** to give you a sense of how it works. +### Request a payment (App-To-User) -In order to make sure that all involved parties (your app, your server, the Pi servers, and the Pi blockchain) are in sync, -the payment needs to go through a **Server-Side Approval** flow and a **Server-Side Completion** flow. +If you want to send Pi from your app to a user, you need to use one of Pi Network's backend SDKs, depending +on the language your backend is written in. Refer to the [Advanced payments guide](./payments_advanced.md) +for more information. + + +In order to make sure that all involved parties (your app, your server, the Pi servers, and the Pi Blockchain) are in sync, +the payment needs to go through a **Server-Side Approval** flow (for User-to-App payment) and/or a **Server-Side Completion** +flow (for all types of payments). Please refer to: * [the full Payments documentation](./payments.md) to learn about the complete payment flow +* [the Advanced Payments documentation](./payments_advanced.md) to learn about App-to-User payment flow * [the Platform API documentation](./platform_API.md) to learn how to confirm the payment and acknowledge it from your server * [the client SDK documentation](./SDK_reference.md) to learn about Pi Apps SDK and provided methods in detail -* the Demo App (coming soon!) to view an example of how you can implement the various required flows in your app's code. +* [the Demo App](https://github.com/pi-apps/demo) to view an example of how you can implement the various required flows in your app's code diff --git a/SDK_reference.md b/SDK_reference.md index d9541eb..580eea8 100644 --- a/SDK_reference.md +++ b/SDK_reference.md @@ -1,4 +1,4 @@ -# Client SDK reference: +# Client SDK reference ## Initialization @@ -41,7 +41,7 @@ to configure this and view your Sandbox URL. ```typescript -Pi.authenticate(scopes: Array, onIncompletePaymentFound: Function): Promise +Pi.authenticate(scopes: Array, onIncompletePaymentFound: Function): Promise ``` Return value: @@ -58,14 +58,7 @@ type AuthResult = { ### `scopes` -Available scopes: `username`, `payments`. - -> **Not yet implemented** -> -> Currently, all calls to the `authenticate` method will assume all scopes have been requested - i.e all calls -> are interpreted as though the first argument were `['username', 'payments']`. -> However, you should implement your app by only adding the scopes you need when calling `authenticate`. -> Scopes support will be added before the general release of the Pi platform. +Available scopes: `username`, `payments`, `wallet_address` Here is a breakdown of various keys available on the `AuthResult['user']` object, and the scopes required for those keys to be present: @@ -74,6 +67,8 @@ to be present: | -------------: | ------------- | :-------------: | | `uid` | An app-local identifier for the user. This is specific to this user, and this app. It will change if the user revokes the permissions they granted to your app. | (none) | | `username` | The user's Pi username. | `username` | +| `payments` | Required if your app needs to make payments between your app and the users | `payments` | +| `wallet_address` | The wallet address of the user who authenticates on your app. | `wallet_address` | ### `onIncompletePaymentFound` @@ -81,7 +76,7 @@ Signature: `(payment: PaymentDTO) => void` Every time when the user is authenticated, and when they try to start a new payment flow, the SDK checks that there is no incomplete payment for this user. An incomplete payment, in this context, is a payment which has been submitted to -the Pi blockchain, but where `status.developer_completed` is still `false` (i.e. the developer has not called the +the Pi Blockchain, but where `status.developer_completed` is still `false` (i.e. the developer has not called the `/complete` endpoint on this payment). If an incomplete payment is found, this callback will be invoked with the payment's `PaymentDTO`. @@ -168,7 +163,7 @@ Read more about Server-Side Approval and the full payment flow in the dedicated Signature: `(paymentId: string, txid: string) => void` -This is called when the user has submitted the transaction to the Pi blockchain. During the completion time period, this callback will be invoked multiple times in case of failure. +This is called when the user has submitted the transaction to the Pi Blockchain. During the completion time period, this callback will be invoked multiple times in case of failure. If the initial trial fails, the Pi SDK will continue to invoke the function roughly every 10 seconds until the completion timer ends. Use this callback to send the blockchain transaction identifier (txid), along with the paymentId @@ -197,37 +192,63 @@ Otherwise, only the first argument will be provided. ### Type `PaymentDTO` -This type is used in the arguments that are passed to `onIncompletePaymentFound` and `onError`. +This type is for the arguments that are passed to `onIncompletePaymentFound` and `onError`. ```typescript type PaymentDTO = { // Payment data: - identifier: string, // The payment identifier - user_uid: string, // The user's app-specific ID - amount: number, // The payment amount - memo: string, // A string provided by the developer, shown to the user - metadata: Object, // An object provided by the developer for their own usage - to_address: string, // The recipient address of the blockchain transaction - created_at: string, // The payment's creation timestamp + identifier: string, // payment identifier + user_uid: string, // user's app-specific ID + amount: number, // payment amount + memo: string, // a string provided by the developer, shown to the user + metadata: Object, // an object provided by the developer for their own usage + from_address: string, // sender address of the blockchain transaction + to_address: string, // recipient address of the blockchain transaction + direction: Direction, // direction of the payment + created_at: string, // payment's creation timestamp + network: AppNetwork, // a network of the payment // Status flags representing the current state of this payment status: { developer_approved: boolean, // Server-Side Approval - transaction_verified: boolean, // Blockchain transaction verified - developer_completed: boolean, // Server-Side Completion - cancelled: boolean, // Cancelled by the developer or by Pi Network - user_cancelled: boolean, // Cancelled by the user + transaction_verified: boolean, // blockchain transaction verified + developer_completed: boolean, // server-Side Completion + cancelled: boolean, // cancelled by the developer or by Pi Network + user_cancelled: boolean, // cancelled by the user }, // Blockchain transaction data: transaction: null | { // This is null if no transaction has been made yet - txid: string, // The id of the blockchain transaction - verified: boolean, // True if the transaction matches the payment, false otherwise - _link: string, // A link to the operation on the Blockchain API + txid: string, // id of the blockchain transaction + verified: boolean, // true if the transaction matches the payment, false otherwise + _link: string, // a link to the operation on the Blockchain API }, } ``` +### Type `Direction` + +A developer can check the direction of the payment with this type. + +```typescript +type Direction = "user_to_app" | "app_to_user" +``` + +### Type `AppNetwork` + +Shows which network the payment is being made on. + +```typescript +type AppNetwork = "Pi Network" | "Pi Testnet" +``` + +### Type `Scope` + +Scopes you can request to users. + +```typescript +type Scope = "username" | "payments" | "wallet_address" +``` ## Share dialog diff --git a/authentication.md b/authentication.md new file mode 100644 index 0000000..81b1b34 --- /dev/null +++ b/authentication.md @@ -0,0 +1,18 @@ +# Authentication + +This is a simple walkthrough on handling user authentication using Pi SDK and API endpoint. For a detailed explanation, please refer to [Pi.authenticate](./SDK_reference.md#authentication) for SDK reference and [/me](./platform_API.md#authentication) for API reference. +## Guide + +Here is a list of steps you can follow when you authenticate users for your app: +### 1. Call `authenticate()` of Pi SDK + +Using the Pi SDK `authenticate()`, you can obtain user information along with the access token. +```javascript +const authRes = await window.Pi.authenticate(scopes, onIncompletePaymentFound); +``` + +### 2. Make a GET request to `/me` Pi API endpoint using the access token for verification +To verify the data you got in step 1, you need to make a GET request to `/me` Pi API endpoint, with the access token included in the header. If the access token is valid, it will return a response with [UserDTO](./platform_API#UserDTO). However, if the token is invalid, it will return HTTP 401 Unauthorized code. +```javascript +const me = await axios.get('https://api.minepi.com/v2/me', {headers: {'Authorization': `Bearer ${accessToken}}}); +``` \ No newline at end of file diff --git a/developer_portal.md b/developer_portal.md index 6da6971..5427bfe 100644 --- a/developer_portal.md +++ b/developer_portal.md @@ -4,78 +4,88 @@ With the help of Pi SDK and Pi API, you can create applications that run within ## How to register your app -1. The Pi Developer Portal can be accessed using the Pi Browser. Go to `pi://develop.pi` to visit the Pi Developer Portal. To register a new app, click on `New App` button at the bottom of the page. +1. The Pi Developer Portal can be accessed using the Pi Browser. Go to `pi://develop.pi` to visit the Pi Developer Portal. When you first get to the main page, you won't see any app. To register your app, tab on the "New App" button.
- drawing + drawing
+
-2. You can fill in the required fields. One important field is selecting the host network that the app is connecting to. Depending on this option, Pi SDK will automatically connect your app to the corresponding network. An app can only connect to one network at a time, and once you register the app, this option cannot be changed. +2. Initially you're asked to fill in 3 required fields. The "App Network" option lets you select the host network that your app is connecting to. Depending on this option, Pi SDK will automatically connect your app to the corresponding network, either to Pi Mainnet or Pi Testnet. Note that an app can only connect to one network at a time, and once you register the app, this option cannot be changed. What this means is you're advised to create two different apps, one with testnet for testing purpose and one with mainnet for your production usage.
- drawing + drawing
+
-> When the app is connecting to the Pi Testnet, you can maintain a list of whitelisted users. Your testnet app will only be accessible by users you allowed, and if you leave this field empty, anyone can access your test app. +3. After you register your app, you can see your app in detail. Each app has its own "App Checklist", which helps you keep track of required steps to successfully set up your app. To see the checklist, tab on "App Checklist" button.
- drawing + drawing
+
-> When the app is connecting to the Pi Mainnet, you can pair one of your testnet apps to the mainnet app. More specific usage is coming soon in the future. +4. The checklist steps will be unlocked sequentially as you complete each step. The first step is to configure the hosting option.
- drawing + drawing
+
-> When you're hosting the app on your server, you will also need to provide the url. Notice that you'll be asked to verify the ownership of the url after you register the app. After you filled in the required fields, you can submit to register your app by clicking on `Submit` button at the bottom of the page. +5. Once you configure the hosting option, you'll see that "App Wallet" button is now enabled, and the next step for checklist is connecting a wallet to the app. Follow the instruction to create the app and connect it to your app. -3. After you register your app, you can see your apps in the main page. If you selected the paired app for your mainnet app, it will show like the following. +
+ drawing +
+
+ +6. When you connect your app wallet to your app, the checklist will show you documentations that you can go over to get started. From here, you can have a look and follow the remaining steps to fully configure the app.
- drawing + drawing
-
+
## Testnet app in the Pi Browser If you registered your app to connect to the Pi Testnet and if you visit your app in the Pi Browser, it will show the black and yellow stripe at the top to indicate that this app is connected to the Pi Testnet.
- drawing + drawing
- -## Legacy Project created before 26/07/2022 +## Legacy Project created before 26/07/2022 Projects that existed prior to the launch of the Pi Mainnet SDK will point to the Pi Testnet + - This cannot be changed or updated - It is best practice to create new Developer Portal Projects ### Developers and Teams with previously created Legacy Projects -1. Create a new Developer Portal Project - - Select Mainnet - This will be the Mainnet Version of the App - - URL - - This project should contain the desired URL that Pioneers will access the app with through the Pi Browser - - URL ownership will be determined through verification process - - Payment Wallet - - Until developer/app wallets are created the wallet address of the developer who creates the new project page will be used to process all transactions - - If the project page creator does not have a Pi Wallet Address which has been created in a Mainnet Migration all transactions will fail. +1. Create a new Developer Portal Project + - Select Mainnet - This will be the Mainnet Version of the App + - URL + - This project should contain the desired URL that Pioneers will access the app with through the Pi Browser + - URL ownership will be determined through verification process + - Payment Wallet + - Until developer/app wallets are created the wallet address of the developer who creates the new project page will be used to process all transactions + - If the project page creator does not have a Pi Wallet Address which has been created in a Mainnet Migration all transactions will fail. 2. Create a second new Developer Project Page - - Select Testnet - This will be for testing purposes - - URL - - Cannot be the same as the Mainnet URL - - Must be owned by the developer as well - - Set the desired access permissions - - This project can be linked to the previously created Mainnet Project from step 1 + - Select Testnet - This will be for testing purposes + - URL + - Cannot be the same as the Mainnet URL + - Must be owned by the developer as well + - Set the desired access permissions + - This project can be linked to the previously created Mainnet Project from step 1 3. Link Mainnet Project to the Brainstorm project (if applicable) - - As of July 2022 it is possible to link only one developer portal project to a brainstorm project + - As of July 2022 it is possible to link only one developer portal project to a brainstorm project ### Special Considerations + - If an app team has no members with a Mainnet Wallet - - Please reach out to the Pi CT through the Pi Support Portal - - For the question “What does your question relate to? ” - - Select “Pi Mainnet SDK Wallet” - - Submit contact information - - A member of the Pi CT will follow up + - Please reach out to the Pi CT through the Pi Support Portal + - For the question “What does your question relate to? ” + - Select “Pi Mainnet SDK Wallet” + - Submit contact information + - A member of the Pi CT will follow up diff --git a/img/dev_portal_app_main_1.png b/img/dev_portal_app_main_1.png new file mode 100644 index 0000000..ebe8587 Binary files /dev/null and b/img/dev_portal_app_main_1.png differ diff --git a/img/dev_portal_app_main_2.png b/img/dev_portal_app_main_2.png new file mode 100644 index 0000000..df929fe Binary files /dev/null and b/img/dev_portal_app_main_2.png differ diff --git a/img/dev_portal_checklist_1.png b/img/dev_portal_checklist_1.png new file mode 100644 index 0000000..ffe680b Binary files /dev/null and b/img/dev_portal_checklist_1.png differ diff --git a/img/dev_portal_checklist_2.png b/img/dev_portal_checklist_2.png new file mode 100644 index 0000000..58bd95f Binary files /dev/null and b/img/dev_portal_checklist_2.png differ diff --git a/img/dev_portal_create_app.png b/img/dev_portal_create_app.png new file mode 100644 index 0000000..93060ea Binary files /dev/null and b/img/dev_portal_create_app.png differ diff --git a/img/dev_portal_main.png b/img/dev_portal_main.png new file mode 100644 index 0000000..ae83b2c Binary files /dev/null and b/img/dev_portal_main.png differ diff --git a/img/dev_portal_main_1.png b/img/dev_portal_main_1.png deleted file mode 100644 index b11c47e..0000000 Binary files a/img/dev_portal_main_1.png and /dev/null differ diff --git a/img/dev_portal_main_2.png b/img/dev_portal_main_2.png deleted file mode 100644 index 463decf..0000000 Binary files a/img/dev_portal_main_2.png and /dev/null differ diff --git a/img/dev_portal_new_1.png b/img/dev_portal_new_1.png deleted file mode 100644 index 87a0bb4..0000000 Binary files a/img/dev_portal_new_1.png and /dev/null differ diff --git a/img/dev_portal_new_2.png b/img/dev_portal_new_2.png deleted file mode 100644 index 3ba27e2..0000000 Binary files a/img/dev_portal_new_2.png and /dev/null differ diff --git a/img/dev_portal_new_3.png b/img/dev_portal_new_3.png deleted file mode 100644 index 9ae851f..0000000 Binary files a/img/dev_portal_new_3.png and /dev/null differ diff --git a/payments.md b/payments.md index 912a5fe..c8824ef 100644 --- a/payments.md +++ b/payments.md @@ -1,12 +1,12 @@ # Payments Payments are wrappers around blockchain transactions, which enable your app, -the Pi blockchain, and the Pi Servers to be all synchronized when the user +the Pi Blockchain, and the Pi Servers to be all synchronized when the user submits a blockchain transaction to pay for something in your app. They enable you, the developer of the app, to have full confidence that the user has actually made the transaction, while not having to -bother with the technicalities involved when interacting with the Pi blockchain. +bother with the technicalities involved when interacting with the Pi Blockchain. ## The Payment flow @@ -33,7 +33,7 @@ After they're created, payments go through 3 major phases: **Phase II - User interaction and blockchain transaction** At this stage, the payment dialog becomes interactive and enables the -user to confirm the transaction, sign it, and submit it to the Pi blockchain. +user to confirm the transaction, sign it, and submit it to the Pi Blockchain. You do not have anything to do at this stage, everything is handled by the Pi Apps Platform and the Pi Wallet. diff --git a/payments_advanced.md b/payments_advanced.md new file mode 100644 index 0000000..6086988 --- /dev/null +++ b/payments_advanced.md @@ -0,0 +1,52 @@ +# Payments Advanced + +While the Pi Frontend Javascript SDK supports creating a U2A (User-To-App) payment, your app might need an ability to +make an A2U (App-To-User) payment. In this documentation, we are going to show you how you can make an A2U payment. + +Please note that the A2U payments feature is currently available only on the Testnet. + +## Pi Backend SDKs + +Here's a list of Pi Backend SDKs for each language (or runtime) you can use for the A2U payment flow. +| Language | Link | Status | +| :---: | :---: | :---: | +| Ruby | [pi-ruby](https://github.com/pi-apps/pi-ruby) | Officially supported by the Pi Core Team | +| Node.js | [pi-nodejs](https://github.com/pi-apps/pi-nodejs) | **Coming soon!** - Officially supported by the Pi Core Team | +| Python | TBD | Community-maintained | +| PHP | TBD | Community-maintained | + +Community maintainers for other programming languages are more than welcome, please submit a PR in the [PiOS repository](https://github.com/pi-apps/PiOS) if youare interested to maintain a Pi SDK. + + +## Supported features + +This section is a list of features supported by each backend SDK which enables integrating Pi into an app. +Refer to the specific documentation of the library you're using in your project (see table in the previous section) +for specifics on how to use each feature. + +### App-to-user payments + +The current design of A2U payments involves both interacting with the Pi Blockchain and the Pi backend. The Pi blockchain is obviously +the only source of truth for exchanging Pi. The Pi backend is used to improve the end-user experience (e.g. provide users understandable memos +on their wallet, and link backs to your app, while preserving user and developer privacy by not making this information public on the chain) +and to assist developers in avoiding to make payment mistakes (e.g. double payments due to server faults) + +Benefits: + +- **Better user privacy:** This API enables safely accessing a user's wallet address as long as they have consented to +sharing it with your app, and it encourages developers to only access the user's wallet when they have an actual +intent to send them some π, enabling better privacy and user safety. + +- **User wallet accuracy:** The API returns the current user wallet if wallet change was necessary, to avoid the app sending Pi to a deprecated, +inaccessible wallet address for the user. + +- **Better experience for users AND app developers:** Once a transaction has happened the blockchain, it can't be reversed. +Letting the Pi backend servers know about your payment before making a transaction, making the transaction and then informing the backend server one +more time enables recovering the associated metadata and blockchain transaction if a technical issue prevented it from being recorded in your database. +This way the Pi backend, as a thrid party can help you avoid double payments or other bugs that might accidentally deplete your app wallets by accident. +Of course, there are a lot of things that can go wrong and as the developers of your apps you are the only party responsible for managing your app's +wallets and assets. The APIs here are provided for as-is and with no guarantees. + +- **Better integration with the Pi ecosystem:** Using the A2U API enables the payment to be shown in the user's wallet as +coming from your app, instead of looking like a random transaction from an unknown address. This can allow beautiful usr experiences in the future such +as direct links backs to your app from the users' wallets or thumbnail icons displaying the goods the users purchased or returned durectly in their wallets. diff --git a/platform_API.md b/platform_API.md index f4ca663..e9605a5 100644 --- a/platform_API.md +++ b/platform_API.md @@ -54,8 +54,8 @@ Authorization: Key #### Access a user's resource: -Retrieve the user's information. - +Retrieve the user's information, including user information limited to what the user has consented to share +with your app. ``` GET /me @@ -75,12 +75,36 @@ not belong to any real user). ### Payments -Base path: `/payments`. +There are two different payment types. + +1. U2A (User-To-App) +2. A2U (App-To-User) + + +#### Create a payment (U2A): + +If a payment type is U2A, use `createPayment` method of the client-side Javascript SDK to create a payment. You can refer to [Payments](./SDK_reference.md#payments) section for more details. -#### Create a payment: +#### Create a payment (A2U): -Do not create payments using the Platform API. Use the client-side Javascript SDK for this purpose. +``` +POST /payments +``` +* Authorization method: **Server API Key** +* Response type: [PaymentDTO](#PaymentDTO) +Example request body: + +``` +{ + "payment": { + "amount": 1, + "memo": "From app to user test", + "metadata": {"test": "test metadata"}, + "uid": "a1111111-aaaa-bbbb-2222-ccccccc3333d" + } +} +``` #### Get a payment: Get information about a payment. @@ -124,14 +148,47 @@ Example request body: } ``` +#### Cancel a payment: + +Mark the payment as cancelled. + +``` +POST /payments/{payment_id}/cancel +``` + +* Authorization method: **Server API Key** +* Response type: [PaymentDTO](#PaymentDTO) + + +#### Get incomplete server payments: + +Returns the list of server payments (i.e A2U payments) which are in EITHER one of the two states below: + +- payment created, but no blockchain transaction was made yet ; +- blockchain transaction submitted, but the payment has not been completed by the developer. + +``` +GET /payments/incomplete_server_payments +``` + +* Authorization method: **Server API Key** +* Response type: { "incomplete_server_payments": Array<[PaymentDTO](#PaymentDTO)> } + ## Resource types ### `UserDTO` ```typescript { - "uid": string, // An app-specific user identifier - "username": string, // The user's Pi username. Requires the `username` scope. + uid: string, // An app-specific user identifier + credentials: { + scopes: Array, // a list of granted scopes + valid_until: { + timestamp: number, + iso8601: string + } + }, + username?: string, // The user's Pi username. Requires the `username` scope. } ``` @@ -140,28 +197,31 @@ Example request body: ```typescript { // Payment data: - "identifier": string, // The payment identifier - "user_uid": string, // The user's app-specific ID - "amount": number, // The payment amount - "memo": string, // A string provided by the developer, shown to the user - "metadata": Object, // An object provided by the developer for their own usage - "to_address": string, // The recipient address of the blockchain transaction - "created_at": string, // The payment's creation timestamp + identifier: string, // payment identifier + user_uid: string, // user's app-specific ID + amount: number, // payment amount + memo: string, // a string provided by the developer, shown to the user + metadata: Object, // an object provided by the developer for their own usage + from_address: string, // sender address of the blockchain transaction + to_address: string, // recipient address of the blockchain transaction + direction: Direction, // direction of the payment + created_at: string, // the payment's creation timestamp + network: AppNetwork, // a network of the payment // Status flags representing the current state of this payment - "status": { - "developer_approved": boolean, // Server-Side Approval - "transaction_verified": boolean, // Blockchain transaction verified - "developer_completed": boolean, // Server-Side Completion - "cancelled": boolean, // Cancelled by the developer or by Pi Network - "user_cancelled": boolean, // Cancelled by the user + status: { + developer_approved: boolean, // Server-Side Approval + transaction_verified: boolean, // blockchain transaction verified + developer_completed: boolean, // Server-Side Completion + cancelled: boolean, // cancelled by the developer or by Pi Network + user_cancelled: boolean, // cancelled by the user }, // Blockchain transaction data: - "transaction": null | { // This is null if no transaction has been made yet - "txid": string, // The id of the blockchain transaction - "verified": boolean, // True if the transaction matches the payment, false otherwise - "_link": string, // A link to the operation on the Blockchain API + transaction: null | { // This is null if no transaction has been made yet + txid: string, // id of the blockchain transaction + verified: boolean, // true if the transaction matches the payment, false otherwise + _link: string, // a link to the operation on the Blockchain API }, }; -``` +``` \ No newline at end of file