p-sdk-wallet
Version:
A comprehensive wallet SDK for React Native (pwc), supporting multi-chain and multi-account features.
168 lines (167 loc) • 7.57 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SolanaChainService = void 0;
const web3_js_1 = require("@solana/web3.js");
const spl_token_1 = require("@solana/spl-token");
const buffer_1 = require("buffer");
/**
* Service for interacting with Solana blockchain.
* Provides methods for SOL balance checking, SPL token operations, and transaction sending.
*/
class SolanaChainService {
/**
* Creates a new SolanaChainService instance for the specified Solana network.
* @param privateKey - The private key to use for signing transactions (hex string)
* @param chainConfig - The chain configuration to use
* @throws Error if the chain is not a Solana chain
*/
constructor(privateKey, chainConfig) {
if (chainConfig.type !== 'solana') {
throw new Error('SolanaChainService only supports Solana chains');
}
this.connection = new web3_js_1.Connection(chainConfig.rpcUrl, 'confirmed');
this.keypair = web3_js_1.Keypair.fromSecretKey(buffer_1.Buffer.from(privateKey, 'hex'));
}
/**
* Gets the native SOL balance for the wallet.
* @returns Promise resolving to the balance as a bigint in lamports
* @throws Error if the balance query fails
*/
async getNativeBalance() {
try {
const balance = await this.connection.getBalance(this.keypair.publicKey);
return BigInt(balance);
}
catch (error) {
throw new Error(`Failed to get SOL balance: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Sends native SOL to another address.
* @param to - The recipient's public key address
* @param amount - The amount of SOL to send as a string (e.g., "1.5")
* @returns Promise resolving to the transaction response with signature and details
* @throws Error if the transaction fails or recipient address is invalid
*/
async sendTransaction(to, amount) {
try {
const toPubkey = new web3_js_1.PublicKey(to);
const lamports = parseFloat(amount) * web3_js_1.LAMPORTS_PER_SOL;
const transaction = new web3_js_1.Transaction().add(web3_js_1.SystemProgram.transfer({
fromPubkey: this.keypair.publicKey,
toPubkey: toPubkey,
lamports: lamports
}));
const signature = await (0, web3_js_1.sendAndConfirmTransaction)(this.connection, transaction, [this.keypair]);
return {
hash: signature,
from: this.keypair.publicKey.toString(),
to: to
};
}
catch (error) {
throw new Error(`Failed to send SOL transaction: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Gets the balance of a specific SPL token for the wallet.
* @param tokenAddress - The token's mint address
* @returns Promise resolving to the token balance as a bigint
* @throws Error if the balance query fails (returns 0 if token account doesn't exist)
*/
async getTokenBalance(tokenAddress) {
try {
const tokenPubkey = new web3_js_1.PublicKey(tokenAddress);
const associatedTokenAddress = await (0, spl_token_1.getAssociatedTokenAddress)(tokenPubkey, this.keypair.publicKey);
const balance = await this.connection.getTokenAccountBalance(associatedTokenAddress);
if (balance.value === null) {
return BigInt(0);
}
return BigInt(balance.value.amount);
}
catch (error) {
// If token account doesn't exist, return 0
if (error instanceof Error && error.message.includes('TokenAccountNotFoundError')) {
return BigInt(0);
}
throw new Error(`Failed to get token balance: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Gets metadata information about an SPL token.
* @param tokenAddress - The token's mint address
* @returns Promise resolving to token metadata including supply information
* @throws Error if the token info query fails
*/
async getTokenInfo(tokenAddress) {
try {
const tokenPubkey = new web3_js_1.PublicKey(tokenAddress);
// Get token supply
const supply = await this.connection.getTokenSupply(tokenPubkey);
// For now, return basic info. In a real implementation,
// you'd fetch metadata from the token's metadata account
return {
address: tokenAddress,
name: 'Unknown Token',
symbol: 'UNKNOWN',
decimals: 0,
totalSupply: supply.value.amount
};
}
catch (error) {
throw new Error(`Failed to get token info: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Sends SPL tokens to another address.
* @param tokenAddress - The token's mint address to send
* @param to - The recipient's public key address
* @param amount - The amount of tokens to send as a string
* @returns Promise resolving to the transaction response with signature and details
* @throws Error if the transaction fails, insufficient balance, or addresses are invalid
*/
async sendToken(tokenAddress, to, amount) {
try {
const tokenPubkey = new web3_js_1.PublicKey(tokenAddress);
const toPubkey = new web3_js_1.PublicKey(to);
// Get or create associated token account for recipient
const recipientTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(tokenPubkey, toPubkey);
// Get sender's associated token account
const senderTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(tokenPubkey, this.keypair.publicKey);
// Create transfer instruction
const transferInstruction = (0, spl_token_1.createTransferInstruction)(senderTokenAccount, recipientTokenAccount, this.keypair.publicKey, parseFloat(amount));
const transaction = new web3_js_1.Transaction().add(transferInstruction);
const signature = await (0, web3_js_1.sendAndConfirmTransaction)(this.connection, transaction, [this.keypair]);
return {
hash: signature,
from: this.keypair.publicKey.toString(),
to: to
};
}
catch (error) {
throw new Error(`Failed to send token: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Gets the public key address of the wallet.
* @returns The public key address as a string
*/
getAddress() {
return this.keypair.publicKey.toString();
}
/**
* Estimates the transaction fee for a typical transaction.
* @returns Promise resolving to the estimated fee as a bigint in lamports
* @throws Error if the fee estimation fails
*/
async estimateTransactionFee() {
try {
const { feeCalculator } = await this.connection.getRecentBlockhash();
return BigInt(feeCalculator.lamportsPerSignature);
}
catch (error) {
throw new Error(`Failed to estimate transaction fee: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
}
exports.SolanaChainService = SolanaChainService;