Package Exports
- p-sdk-wallet
- p-sdk-wallet/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (p-sdk-wallet) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
PWC Wallet SDK
A comprehensive, secure, and user-friendly wallet SDK for React Native applications. This SDK provides a complete solution for managing cryptocurrency wallets with support for multiple blockchains, HD wallet generation, vanity addresses, NFT support, and advanced features like multi-transfer operations.
📋 Table of Contents
🚀 Quick Start
📱 React Native Usage
⚙️ Configuration
💰 Core Wallet Functions
🔄 Multi-Transfer Operations
🖼️ NFT Functionality
- Get NFT Details
- Get Collection Information
- Validate NFT Contract Address
- NFT Discovery (Backend API)
- Supported APIs
- API Key Setup
- NFT Types and Interfaces
- React Native NFT Component Example
⛽ Advanced Features
🔒 Security & Error Handling
🛠️ Development
Features
- 🔐 Secure HD Wallet Management: BIP-44 compliant hierarchical deterministic wallets
- 🎯 Vanity Address Generation: Generate wallets with custom address prefixes
- 🔗 Multi-Chain Support: Ethereum, BSC, Polygon, Arbitrum, Optimism, Base, and Solana
- 🚀 Multi-Transfer Operations: Batch send tokens to multiple recipients
- 🔧 Custom Chain Support: Add custom chains and override built-in configurations
- 📱 React Native Optimized: Designed specifically for mobile applications
- 🔒 Encryption: AES-256 encryption for secure vault storage
- 🎨 TypeScript: Full TypeScript support with comprehensive type definitions
- 🖼️ NFT Support: Core NFT functionality for individual tokens and collections
Installation
npm install pwc-wallet-sdkQuick Start
1. Basic Wallet Creation
import { Vault } from 'pwc-wallet-sdk';
// Create a new wallet
const { vault, encryptedVault } = await Vault.createNew('your-secure-password');
// Get wallet accounts
const accounts = vault.getAccounts();
console.log('Wallet addresses:', accounts.map(acc => acc.address));2. Vanity Wallet Generation
// Generate wallet with custom address prefix
const { vault, encryptedVault, attempts, foundAddress } =
await Vault.generateVanityHDWallet('your-password', (attempts, currentAddress) => {
console.log(`Attempt ${attempts}: ${currentAddress}`);
});
console.log(`Found address with prefix after ${attempts} attempts: ${foundAddress}`);3. Custom Chain Configuration
import { setupChainConfigs, registerCustomChain, overrideChain } from 'pwc-wallet-sdk';
// Setup custom chains and overrides (call once when app starts)
setupChainConfigs({
// Override built-in chains
overrides: {
'1': { rpcUrl: 'https://my-eth-rpc.com' }, // Use custom Ethereum RPC
'56': { rpcUrl: 'https://my-bsc-rpc.com' }, // Use custom BSC RPC
},
// Add custom chains
customChains: {
'custom-1': {
name: 'My Custom Chain',
rpcUrl: 'https://my-custom-rpc.com',
explorerUrl: 'https://my-explorer.com',
nativeCurrency: { name: 'Token', symbol: 'TKN', decimals: 18 },
type: 'evm'
},
'custom-solana': {
name: 'My Solana Chain',
rpcUrl: 'https://my-solana-rpc.com',
explorerUrl: 'https://my-solana-explorer.com',
nativeCurrency: { name: 'SOL', symbol: 'SOL', decimals: 9 },
type: 'solana'
}
}
});
// Load vault
const vault = await Vault.load(password, encryptedVault);
// Use custom chains normally
await vault.sendToken(from, to, amount, tokenAddress, 'custom-1');
await vault.getNativeBalance(address, 'custom-solana');React Native Usage
Simple Wallet Component
import React, { useState, useEffect } from 'react';
import { Vault, setupChainConfigs } from 'pwc-wallet-sdk';
const WalletComponent = () => {
const [vault, setVault] = useState(null);
const [balance, setBalance] = useState('0');
useEffect(() => {
// Setup custom chains when component mounts
setupChainConfigs({
overrides: {
'1': { rpcUrl: 'https://my-eth-rpc.com' }
},
customChains: {
'custom-1': {
name: 'My Chain',
rpcUrl: 'https://my-rpc.com',
type: 'evm'
}
}
});
loadWallet();
}, []);
const loadWallet = async () => {
try {
const loadedVault = await Vault.load(password, encryptedVault);
setVault(loadedVault);
// Get balance using custom chain
const balance = await loadedVault.getNativeBalance(address, 'custom-1');
setBalance(ethers.formatEther(balance));
} catch (error) {
console.error('Failed to load wallet:', error);
}
};
const sendTransaction = async () => {
if (!vault) return;
try {
// Send using custom chain
const tx = await vault.sendToken(from, to, amount, tokenAddress, 'custom-1');
console.log('Transaction sent:', tx.hash);
} catch (error) {
console.error('Transaction failed:', error);
}
};
return (
<View>
<Text>Balance: {balance}</Text>
<Button title="Send Transaction" onPress={sendTransaction} />
</View>
);
};Custom Hook for Wallet Management
import { useState, useEffect } from 'react';
import { Vault, setupChainConfigs } from 'pwc-wallet-sdk';
export const useWallet = (password: string, encryptedVault: EncryptedData) => {
const [vault, setVault] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
initializeWallet();
}, []);
const initializeWallet = async () => {
try {
setLoading(true);
// Setup chains
setupChainConfigs({
overrides: {
'1': { rpcUrl: 'https://my-eth-rpc.com' }
}
});
const loadedVault = await Vault.load(password, encryptedVault);
setVault(loadedVault);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
const sendToken = async (from: string, to: string, amount: string, tokenAddress: string, chainId: string) => {
if (!vault) throw new Error('Wallet not loaded');
return vault.sendToken(from, to, amount, tokenAddress, chainId);
};
const getBalance = async (address: string, chainId: string) => {
if (!vault) throw new Error('Wallet not loaded');
return vault.getNativeBalance(address, chainId);
};
return {
vault,
loading,
error,
sendToken,
getBalance
};
};Configuration
Vanity Wallet Settings
import { VANITY_WALLET_CONFIG } from 'pwc-wallet-sdk';
// Default settings
console.log(VANITY_WALLET_CONFIG.DEFAULT_PREFIX); // 'aaa'
console.log(VANITY_WALLET_CONFIG.DEFAULT_MAX_ATTEMPTS); // 1000000
console.log(VANITY_WALLET_CONFIG.DEFAULT_CASE_SENSITIVE); // falseSupported Chains
import { SUPPORTED_CHAINS } from 'pwc-wallet-sdk';
// View all supported chains
Object.entries(SUPPORTED_CHAINS).forEach(([chainId, config]) => {
console.log(`${chainId}: ${config.name} (${config.type})`);
});Core Wallet Functions
Account Management
- Add New HD Account
- Add New Solana Account
- Import Account
- Get Accounts
Balance & Token Functions
- Get Native Balance
- Get Token Balance
- Get Token Info
Transaction Functions
- Send Native Token
- Send Token
- Export Mnemonic
Multi-Transfer Operations
- Batch Send Native Tokens
- Batch Send ERC-20 Tokens
NFT Functionality
Get NFT Details
const nftDetail = await vault.getNFTDetail(
'0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D', // contract address
'1234', // tokenId
{ includeMetadata: true, includeCollection: true }
);
console.log(nftDetail);Get Collection Information
const collection = await vault.getNFTCollectionInfo('0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D');
console.log(collection);Validate NFT Contract Address
const isValid = vault.isValidNFTContractAddress('0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D', '1');
console.log('Address is valid:', isValid);NFT Discovery (Backend API)
// Get owned NFTs from your backend
const nfts = await apiClient.get('/nfts/owned', {
address: '0x1234...',
chainId: '1',
limit: 50
});Supported APIs
- Ethereum: Alchemy API (recommended)
- Multi-chain: Covalent API
- Solana: Helius API
API Key Setup
// For Ethereum (Alchemy)
const nftDetail = await vault.getNFTDetail(
contractAddress,
tokenId,
'1', // Ethereum
{ includeMetadata: true },
'your-alchemy-api-key'
);NFT Types and Interfaces
import { NFTDetail, NFTDetailExtended, NFTCollection, NFTOptions } from 'pwc-wallet-sdk';
// Basic NFT information
interface NFTDetail {
contractAddress: string;
tokenId: string;
name: string;
description: string;
image: string;
owner: string;
// ... more properties
}
// Extended NFT information with metadata
interface NFTDetailExtended extends NFTDetail {
attributes?: Array<{ trait_type: string; value: string; display_type?: string }>;
// ... more properties
}
// Collection information
interface NFTCollection {
name: string;
description: string;
image: string;
banner: string;
verified: boolean;
totalSupply: number;
}React Native NFT Component Example
import React, { useState, useEffect } from 'react';
import { View, Text, Image } from 'react-native';
import { Vault, NFTDetailExtended } from 'pwc-wallet-sdk';
const NFTDetailView = ({ vault, contractAddress, tokenId, chainId, apiKey }) => {
const [nft, setNft] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
loadNFTDetail();
}, [contractAddress, tokenId]);
const loadNFTDetail = async () => {
try {
setLoading(true);
const nftDetail = await vault.getNFTDetail(
contractAddress,
tokenId,
chainId,
{ includeMetadata: true },
apiKey
);
setNft(nftDetail);
} catch (error) {
console.error('Failed to load NFT:', error);
} finally {
setLoading(false);
}
};
if (loading) {
return <Text>Loading NFT...</Text>;
}
if (!nft) {
return <Text>NFT not found</Text>;
}
return (
<View style={{ padding: 20 }}>
<Image
source={{ uri: nft.image }}
style={{ width: 300, height: 300 }}
resizeMode="cover"
/>
<Text style={{ fontSize: 24, fontWeight: 'bold', marginTop: 10 }}>
{nft.name}
</Text>
<Text style={{ marginTop: 5 }}>{nft.description}</Text>
<Text style={{ marginTop: 10 }}>
Collection: {nft.contractName}
</Text>
<Text>Token ID: {nft.tokenId}</Text>
</View>
);
};Advanced Features
Gas Estimation
Estimate Native Transfer Gas
const gasEstimate = await vault.estimateNativeTransferGas(
fromAddress,
toAddress,
amount,
'1'
);
console.log('Estimated gas:', gasEstimate.toString());
console.log('Estimated cost (in ETH):', ethers.formatEther(gasEstimate * gasPrice));Estimate Token Transfer Gas
const gasEstimate = await vault.estimateTokenTransferGas(
fromAddress,
tokenAddress,
toAddress,
amount,
'1'
);
console.log('Estimated gas for token transfer:', gasEstimate.toString());Estimate Multi-Transfer Gas
const recipients = [
{ address: '0x1111...', amount: '0.01' },
{ address: '0x2222...', amount: '0.02' },
{ address: '0x3333...', amount: '0.005' }
];
// Estimate for native token multi-transfer
const nativeGasEstimate = await vault.estimateMultiTransferGas(
fromAddress,
recipients,
'1', // Ethereum
true // Native tokens
);
// Estimate for token multi-transfer
const tokenGasEstimate = await vault.estimateMultiTransferGas(
fromAddress,
recipients,
'1', // Ethereum
false, // ERC-20 tokens
tokenAddress // USDC
);
console.log('Native multi-transfer gas:', nativeGasEstimate.toString());
console.log('Token multi-transfer gas:', tokenGasEstimate.toString());Security Considerations
- Password Strength: Use strong passwords for vault encryption
- Private Key Storage: Private keys are never stored in plain text
- Memory Safety: Sensitive data is cleared from memory when possible
- Encryption: All vault data is encrypted using AES-256
- Validation: Input validation prevents common attack vectors
Error Handling
try {
const vault = await Vault.load(password, encryptedVault);
await vault.sendToken(from, to, amount, tokenAddress, '1');
} catch (error) {
if (error.message.includes('incorrect password')) {
// Handle password error
} else if (error.message.includes('insufficient balance')) {
// Handle balance error
} else {
// Handle other errors
}
}Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
License
MIT License - see LICENSE file for details.