Pi Network Wallets
Setting up a developer wallet and implementing the payment application flow on the Pi Network requires coordinating your application frontend, backend server, and the Pi Blockchain.
Developer Wallet Setup
To handle transactions, you must register your application and configure your developer credentials using the Pi Developer Portal inside the Pi Browser.
Registering the Application
- Access Portal: Open the Pi Browser and navigate to pi://develop.pi
- Create App: Click New App, and fill out your App Name and Description.
- Select Network: Choose either Pi Testnet (for development) or Pi Mainnet (for production).
Configuring the Wallet & Keys
- Generate Keys: Inside your registered app dashboard on the portal, locate the Wallet Configuration section.
- Save Keypair: Generate a new application wallet. Securely copy the Public Key (wallet address) and the Secret Seed/Passphrase.
- Backend Storage: Store the secret passphrase securely in your server’s environment variables. Never expose this secret key on your frontend client.
- Get API Key: Generate an application API Key from the portal to authorize your backend server's requests to the Pi servers.
Wallet Application Payment Flow
Pi Network relies on a strict 3-phase synchronization flow (Frontend → Backend Server → Pi Core Server → Pi Blockchain) to ensure security and prevent double-spending.
There are two payment directions: User-to-App (U2A) and App-to-User (A2U).
Option A: User-to-App (U2A) Flow (User pays the App)
[ Pioneer / Frontend ] ----(1. Initiate)----> [ Developer Server ]
| |
(3. Sign & Submit) (2. Approve)
| |
v v
[ Pi Blockchain ] <--------(4. Sync)---------> [ Pi Core Server ]
Phase I: Creation & Server-Side Approval
- Initiate Payment: The user clicks a checkout button on your web frontend. Your frontend calls Pi.createPayment() via the Pi JavaScript SDK.
- Pending State: The Pi Platform creates a pending payment tracking object and returns a paymentId to your frontend.
- Server Approval: Your frontend sends this paymentId to your developer backend server. Your backend submits a POST request to the Pi Server endpoint (/v2/payments/:payment_id/approve) using your developer API key. This confirms your server expects this payment.
Phase II: User Authentication & Blockchain Execution
- User Prompt: Once approved by your server, the Pi Browser automatically opens a native, secure payment overlay to the user.
- Signing: The user reviews the details, inputs their personal wallet passphrase (or biometric ID), and signs the transaction.
- Submission: The transaction is submitted directly to the Pi Blockchain, shifting the funds from the user's wallet to your developer wallet.
Phase III: Server-Side Completion
- Tx Proof: The blockchain processes the transaction and returns a transaction recipe (txid) to the frontend.
- Finalize: Your frontend sends the txid to your backend server. Your backend makes a final POST request to the Pi Server endpoint (/v2/payments/:payment_id/complete) to mark the transaction as fully resolved, allowing you to safely deliver the digital good.
Option B: App-to-User (A2U) Flow (App pays or rewards the User)
This flow is used for payouts, rewards, or withdrawals. It bypasses user interaction because the funds move directly out of your developer wallet.
- Create Payout Request: Your backend server makes a POST request to the Pi API api.minepi.com/v2/payments specifying the recipient's wallet address and amount.
- Account Check: Your server must fetch and verify the status of the target user's wallet account on the blockchain before moving forward.
- Build & Sign: Your backend programmatically builds the blockchain transaction and signs it locally using your stored Developer Secret Seed.
- Broadcast: The signed transaction is sent directly to the Pi network nodes for validation and final block commitment.
JS SDK
The Pi Network JS SDK exposes wallet-related operations and blockchain
interactions via the window.Pi.Wallet module. These methods enable
your app to create, submit, and inspect Pi blockchain transactions for
authenticated users, only within the Pi Browser.
This guide demonstrates how to integrate the Pi SDK into many application frameworks. This example shows how to initialize the Pi SDK, authenticate a Pioneer, and create a payment request inside a Pi app.
The pi-sdk-js
package
is part of the “Ten Minutes to Transactions” effort described in this
video.
If you, or your GenAI agent, are planning to use the Pi SDK modules in this documentation for your app, it is highly suggested that you use this package rather than implement transaction processing by hand with the core Pi SDK. The three way handshake between client, server, and the Pi servers required is provded for you.
Note: Pi SDK authentication and payment features require the application to run inside the Pi Browser.
Purpose
- Enable wallet-related operations and blockchain interactions in the Pi Browser
- Create, submit, and inspect Pi blockchain transactions within the Pi Browser
Overview
- Purpose: Wallet-related operations and access.
- Example available (functions may differ by SDK version):
JavaScript
window.Pi.Wallet.submitTransaction(xdr)
window.Pi.Wallet.getUserMigratedWalletAddresses()
- All methods are Promise-based.
window.Pi.Wallet Methods
.submitTransaction(xdr)
- Purpose: Submits a pre-signed Stellar XDR transaction to the Pi Blockchain via the user’s authenticated wallet.
- Parameters:
xdr(string): Base64-encoded Stellar XDR representing the transaction
- Returns:
Promise<object>: Resolved with the blockchain transaction result if success, or rejects on error (user cancel, auth problem, RPC failure, etc.).
- Example:
JavaScript
Pi.Wallet.submitTransaction(xdr).then(function(result) {
// Transaction submitted! Process result or notify user
}).catch(function(error) {
// Submission failed; handle error
});
Pi.Wallet.getUserMigratedWalletAddresses()
- Purpose: Returns a list of wallet addresses controlled by the user (mainnet and/or testnet, as migrated from Pi Network). Useful for apps needing to display blockchain identity details.
- Returns:
Promise<object>: An object with awalletsarray, each containing{ publicKey: string }.
- Example:
JavaScript
Pi.Wallet.getUserMigratedWalletAddresses().then(function(data) {
data.wallets.forEach(function(wallet) {
console.log('Wallet address:', wallet.publicKey);
});
});
Typical Usage Pattern
JavaScript
// Submit an existing signed transaction
const signedXDR = "AAAA...";
Pi.Wallet.submitTransaction(signedXDR)
.then(txResult => { console.log("Tx Success!", txResult); })
.catch(err => { alert("Tx failed: " + err.message); });
// Get user's wallet addresses
Pi.Wallet.getUserMigratedWalletAddresses()
.then(data => {
// [{ publicKey: "G..." } ...]
doSomething(data.wallets);
});
Additional Notes & Best Practices
- Only call Wallet methods after user authentication (
Pi.authenticate(...)). - Transactions must be pre-signed; the SDK does not build or sign transactions for you. See Stellar docs on creating XDR.
- Always handle errors: the user may cancel, reject, or lose connection, or the transaction might fail at the blockchain layer.
- Use
.getUserMigratedWalletAddresses()to display or confirm available wallet addresses for advanced flows. - Advanced: For custom flows (advanced custody, app-to-user payments, etc.) see the advanced payments and SDK reference.