├── LICENSE.md └── README.md /LICENSE.md: -------------------------------------------------------------------------------- 1 | PiOS License 2 | 3 | Copyright (C) 2023 Pi Community Company 4 | 5 | Permission is hereby granted by the application software developer (“Software Developer”), free 6 | of charge, to any person obtaining a copy of this application, software and associated 7 | documentation files (the “Software”), which was developed by the Software Developer for use on 8 | Pi Network, whereby the purpose of this license is to permit the development of derivative works 9 | based on the Software, including the right to use, copy, modify, merge, publish, distribute, 10 | sub-license, and/or sell copies of such derivative works and any Software components incorporated 11 | therein, and to permit persons to whom such derivative works are furnished to do so, in each case, 12 | solely to develop, use and market applications for the official Pi Network. For purposes of this 13 | license, Pi Network shall mean any application, software, or other present or future platform 14 | developed, owned or managed by Pi Community Company, and its parents, affiliates or subsidiaries, 15 | for which the Software was developed, or on which the Software continues to operate. However, 16 | you are prohibited from using any portion of the Software or any derivative works thereof in any 17 | manner (a) which infringes on any Pi Network intellectual property rights, (b) to hack any of Pi 18 | Network’s systems or processes or (c) to develop any product or service which is competitive with 19 | the Pi Network. 20 | 21 | The above copyright notice and this permission notice shall be included in all copies or 22 | substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 25 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 26 | AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS, PUBLISHERS, OR COPYRIGHT HOLDERS OF THIS 27 | SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL 28 | DAMAGES (INCLUDING, BUT NOT LIMITED TO BUSINESS INTERRUPTION, LOSS OF USE, DATA OR PROFITS) 29 | HOWEVER CAUSED AND UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 30 | TORT (INCLUDING NEGLIGENCE) ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 31 | OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 32 | 33 | Pi, Pi Network and the Pi logo are trademarks of the Pi Community Company. 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pi Network SDK Integration Guide 2 | 3 | The following guide explains how to build a Pi SDK for any programming language, and how to integrate app-to-user (A2U) 4 | payments into it. It walks you through how to use the various building blocks to achieve the A2U payment process. 5 | 6 | Code snippets in this documentation are meant as high-level examples of the required steps, and will NOT run 7 | if they are copy-pasted into an existing project. They are written in Javascript, but the whole point of 8 | this document is to explain how to build a Pi SDK in _ANY language other_ than JS. 9 | 10 | If you need to integrate Pi into your Node.JS project, you're looking for the 11 | [Pi SDK for Node.JS](https://github.com/pi-apps/pi-nodejs). 12 | 13 | 14 | ## Building blocks 15 | 16 | A2U payments involve both interacting with the Pi Blockchain and the Pi backend. The Pi blockchain is obviously the 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) 17 | 18 | Your Pi SDK implementation needs to both be able to sign and submit blockchain transactions using the Stellar SDK and send additional API calls to the Pi backend using standard https libraries. As a reference, here is the list of the [official Stellar SDK](https://developers.stellar.org/docs/tools-and-sdks#sdk-library)'s in various languages. You will need to pick the one that is applicable to the language you are working on, include it as dependency into your SDK, and use it as needed. 19 | 20 | 21 | ## Integration Guide 22 | 23 | ### Overall flow 24 | 25 | There are certain steps you need to follow to make A2U payment. Before we take a look at the overall flow, there's one thing to keep in mind. 26 | 27 | > **important** At the moment, you can process only one A2U payment at a time, due to the nature of sequence number requirement on the Pi Blockchain. This is a safety feature of the blockchain. However, we will support batch payments, *i.e. creating an A2U payment with multiple user uids,* to increase the throughput. This is possible through simply adding more _operations_ into each _transaction_. 28 | 29 | You essentiall need to encapsulate the following API calls into convenient SDK functions: 30 | 31 | 1. Send API request to the Pi server to create a payment 32 | > Similarly to the U2A payments where app developers create a payment using the Pi SDK's `createPayment` method, you need to implement a method that creates a payment through an API endpoint `api.minepi.com/v2/payments`. 33 | - Unlike U2A payment, which requires the Server-Side Approval, A2U payments do not require any approval from the developer 34 | before a transaction can be sumitted, since the flow starts from the app side and not from the user's side. 35 | 36 | 2. Load the account 37 | > You need to look up the account every time before submitting a transaction, even if the Pi server gave you its address in the past. That's because the account could have been destroyed on the blockchain or the user could have changed their active wallet. By following this recommendation, developers can save the transaction fee that might have been wasted and avoid sending Pi to the wrong address. Remember that the transaction fee still gets spent even if a transaction fails. 38 | 39 | 3. Build the transaction 40 | > You need to build a transaction with the relevant data such as the recipient's wallet address. 41 | 42 | 4. Sign the transaction 43 | > After you build the transaction, you need to sign with the developer's keypair. Retrieving the keypair requires the secret seed. 44 | 45 | 5. Submit the transaction to the Pi blockchain 46 | > This is when the transaction is sent to the Pi blockchain. Depending on the status, you will get a corresponding response. 47 | 48 | 6. Complete the payment by sending an API request to the `/complete` endpoint 49 | > The transaction will be verified by the Pi server after you submit it in the previous step. Send an API request to the `/complete` endpoint to check the status and complete the payment. 50 | 51 | 52 | ### Example integration: 53 | 54 | We are going to follow each step shown in the "Overall flow" section above to make an A2U payment. 55 | 56 | It is worth noting that although `js-stellar-sdk` is available both on the frontend and backend, 57 | since the A2U is a server-side operation, we are providing Node.js examples. 58 | 59 | 1. Send API request to the Pi server to create a payment 60 | 61 | ```javascript 62 | const axios = require('axios'); 63 | 64 | // API Key of your app, available in the Pi Developer Portal 65 | // DO NOT hardcode this, read it from an environment variable and treat it like a production secret. 66 | const PI_API_KEY = "YOUR_PI_API_KEY" 67 | 68 | const axiosClient = axios.create({baseURL: 'https://api.minepi.com', timeout: 20000}); 69 | const config = {headers: {'Authorization': `Key ${PI_API_KEY}`, 'Content-Type': 'application/json'}}; 70 | 71 | // This is the user UID of this payment's recipient 72 | const userUid = "a1111111-aaaa-bbbb-2222-ccccccc3333d" // this is just an example uid! 73 | const body = {amount: 1, memo: "Memo for user", metadata: {test: "your metadata"}, uid: userUid}; // your payment data and uid 74 | 75 | let paymentIdentifier; 76 | let recipientAddress; 77 | 78 | axiosClient.post(`/v2/payments`, body, config).then(response => { 79 | paymentIdentifier = response.data.identifier; 80 | recipientAddress = response.data.recipient; 81 | }); 82 | 83 | ``` 84 | 85 | 2. Load the account 86 | 87 | ```javascript 88 | const StellarSdk = require('stellar-sdk'); 89 | 90 | const myPublicKey = "G_YOUR_PUBLIC_KEY" // your public key, starts with G 91 | 92 | // an object that let you communicate with the Pi Testnet 93 | // if you want to connect to Pi Mainnet, use 'https://api.mainnet.minepi.com' instead 94 | const piTestnet = new StellarSdk.Server('https://api.testnet.minepi.com'); 95 | 96 | let myAccount; 97 | piTestnet.loadAccount(myPublicKey).then(response => myAccount = response); 98 | 99 | let baseFee; 100 | piTestnet.fetchBaseFee().then(response => baseFee = response); 101 | ``` 102 | 103 | 3. Build the transaction 104 | 105 | ```javascript 106 | // create a payment operation which will be wrapped in a transaction 107 | let payment = StellarSdk.Operation.payment({ 108 | destination: recipientAddress, 109 | asset: StellarSdk.Asset.native(), 110 | amount: body.amount.toString() 111 | }); 112 | 113 | // 180 seconds timeout 114 | let timebounds; 115 | piTestnet.fetchTimebounds(180).then(response => timebounds = response); 116 | 117 | let transaction = new StellarSdk.TransactionBuilder(myAccount, { 118 | fee: baseFee, 119 | networkPassphrase: "Pi Testnet", // use "Pi Network" for mainnet transaction 120 | timebounds: timebounds 121 | }) 122 | .addOperation(payment) 123 | // IMPORTANT! DO NOT forget to include the payment id as memo 124 | .addMemo(StellarSdk.Memo.text(paymentIdentifier)); 125 | transaction = transaction.build(); 126 | ``` 127 | 128 | 4. Sign the transaction 129 | 130 | ```javascript 131 | // See the "Obtain your wallet's private key" section above to get this. 132 | // And DON'T HARDCODE IT, treat it like a production secret. 133 | const mySecretSeed = "S_YOUR_SECRET_SEED"; // NEVER expose your secret seed to public, starts with S 134 | const myKeypair = StellarSdk.Keypair.fromSecret(mySecretSeed); 135 | transaction.sign(myKeypair); 136 | ``` 137 | 138 | 5. Submit the transaction to the Pi blockchain 139 | 140 | ```javascript 141 | let txid; 142 | piTestnet.submitTransaction(transaction).then(response => txid = response.id); 143 | ``` 144 | 145 | 6. Complete the payment by sending API request to `/complete` endpoint 146 | 147 | ```javascript 148 | // check if the response status is 200 149 | let completeResponse; 150 | axiosClient.post(`/v2/payments/${paymentIdentifier}/complete`, {txid}, config).then(response => completeResponse = response); 151 | ``` 152 | --------------------------------------------------------------------------------