UNPKG

@pod-protocol/sdk-js

Version:
282 lines (251 loc) 9.1 kB
'use strict'; var base = require('../base-B0PMFl1k.js'); var web3_js = require('@solana/web3.js'); var anchor = require('@coral-xyz/anchor'); var utils_pda = require('../utils/pda.js'); /** * Escrow service for PoD Protocol SDK */ /** * Service for managing escrow deposits and payments in the PoD Protocol * * @class EscrowService * @extends BaseService */ class EscrowService extends base.BaseService { /** * Deposit funds into escrow for a channel * @param {Object} options - Deposit options * @param {Object} wallet - Depositor's wallet * @returns {Promise<string>} Transaction signature * * @example * ```javascript * const tx = await client.escrow.deposit({ * channel: channelPDA, * amount: 5000000 // lamports * }, wallet); * ``` */ async deposit(options, wallet) { if (!this.isInitialized()) { throw new Error('Service not initialized. Call client.initialize() first.'); } // Derive PDAs const [agentPDA] = await utils_pda.findAgentPDA(wallet.publicKey, this.programId); // Derive escrow PDA const [escrowPDA] = await utils_pda.findEscrowPDA(options.channel, wallet.publicKey, this.programId); return this.retry(async () => { const tx = await this.program.methods .depositEscrow(new anchor.BN(options.amount)) .accounts({ escrowAccount: escrowPDA, channel: options.channel, depositor: wallet.publicKey, depositorAgent: agentPDA, systemProgram: web3_js.SystemProgram.programId }) .rpc(); return tx; }); } /** * Withdraw funds from escrow * @param {Object} options - Withdrawal options * @param {Object} wallet - Depositor's wallet * @returns {Promise<string>} Transaction signature * * @example * ```javascript * const tx = await client.escrow.withdraw({ * channel: channelPDA, * amount: 1000000 // lamports * }, wallet); * ``` */ async withdraw(options, wallet) { if (!this.isInitialized()) { throw new Error('Service not initialized. Call client.initialize() first.'); } // Derive PDAs const [agentPDA] = await utils_pda.findAgentPDA(wallet.publicKey, this.programId); // Derive escrow PDA const [escrowPDA] = await utils_pda.findEscrowPDA(options.channel, wallet.publicKey, this.programId); return this.retry(async () => { const tx = await this.program.methods .withdrawEscrow(new anchor.BN(options.amount)) .accounts({ escrowAccount: escrowPDA, channel: options.channel, depositor: wallet.publicKey, depositorAgent: agentPDA, systemProgram: web3_js.SystemProgram.programId }) .rpc(); return tx; }); } /** * Get escrow account by channel and depositor * @param {string} channel - Channel public key * @param {string} depositor - Depositor's public key * @returns {Promise<Object|null>} Escrow account data * * @example * ```javascript * const escrow = await client.escrow.get(channelPDA, depositorAddress); * if (escrow) { * console.log('Escrow balance:', escrow.balance); * } * ``` */ async get(channel, depositor) { if (!this.isInitialized()) { throw new Error('Service not initialized. Call client.initialize() first.'); } try { const [escrowPDA] = await utils_pda.findEscrowPDA(channel, depositor, this.programId); const escrowAccount = await this.program.account.escrowAccount.fetch(escrowPDA); return { pubkey: escrowPDA, ...escrowAccount, // Convert BN to number for JavaScript compatibility balance: escrowAccount.balance.toNumber(), createdAt: escrowAccount.createdAt.toNumber(), lastUpdated: escrowAccount.lastUpdated.toNumber() }; } catch (error) { if (error.message?.includes('Account does not exist')) { return null; } throw error; } } /** * List escrow accounts by depositor * @param {string} depositor - Depositor's public key * @param {Object} [options] - Query options * @param {number} [options.limit=50] - Maximum number of results * @returns {Promise<Object[]>} Array of escrow accounts * * @example * ```javascript * const escrows = await client.escrow.getByDepositor(depositorAddress, { limit: 20 }); * ``` */ async getByDepositor(depositor, options = {}) { if (!this.isInitialized()) { throw new Error('Service not initialized. Call client.initialize() first.'); } try { const accounts = await this.program.account.escrowAccount.all(); let escrows = accounts .filter(account => account.account.depositor.equals(depositor)) .map(account => ({ channel: account.account.channel, depositor: account.account.depositor, balance: account.account.balance?.toNumber() || 0, amount: account.account.balance?.toNumber() || 0, createdAt: account.account.createdAt?.toNumber() || Date.now(), lastUpdated: account.account.lastUpdated?.toNumber() || Date.now(), bump: account.account.bump })); // Sort by creation date (newest first) escrows.sort((a, b) => b.createdAt - a.createdAt); if (options.limit) { escrows = escrows.slice(0, options.limit); } return escrows; } catch (error) { throw new Error(`Failed to get escrows by depositor: ${error.message}`); } } /** * List escrow accounts by channel * @param {string} channel - Channel public key * @param {Object} [options] - Query options * @param {number} [options.limit=50] - Maximum number of results * @returns {Promise<Object[]>} Array of escrow accounts * * @example * ```javascript * const escrows = await client.escrow.getByChannel(channelPDA, { limit: 20 }); * ``` */ async getByChannel(channel, options = {}) { if (!this.isInitialized()) { throw new Error('Service not initialized. Call client.initialize() first.'); } try { const accounts = await this.program.account.escrowAccount.all(); let escrows = accounts .filter(account => account.account.channel.equals(channel)) .map(account => ({ channel: account.account.channel, depositor: account.account.depositor, balance: account.account.balance?.toNumber() || 0, amount: account.account.balance?.toNumber() || 0, createdAt: account.account.createdAt?.toNumber() || Date.now(), lastUpdated: account.account.lastUpdated?.toNumber() || Date.now(), bump: account.account.bump })); // Sort by creation date (newest first) escrows.sort((a, b) => b.createdAt - a.createdAt); if (options.limit) { escrows = escrows.slice(0, options.limit); } return escrows; } catch (error) { throw new Error(`Failed to get escrows by channel: ${error.message}`); } } /** * Get total escrow balance for a channel * @param {string} channel - Channel public key * @returns {Promise<number>} Total balance in lamports * * @example * ```javascript * const totalBalance = await client.escrow.getTotalBalance(channelPDA); * console.log('Total escrow balance:', totalBalance); * ``` */ async getTotalBalance(channel) { const escrows = await this.getByChannel(channel); return escrows.reduce((total, escrow) => total + escrow.balance, 0); } /** * Check if depositor has sufficient escrow balance for a channel * * @param {string} channel - Channel public key * @param {string} depositor - Depositor's public key * @param {number} requiredAmount - Required amount in lamports * @returns {Promise<boolean>} True if sufficient balance * * @example * ```javascript * const hasSufficientBalance = await client.escrow.hasSufficientBalance( * channelPDA, * depositorAddress, * 1000000 * ); * ``` */ async hasSufficientBalance(channel, depositor, requiredAmount) { const escrow = await this.get(channel, depositor); return escrow ? escrow.balance >= requiredAmount : false; } /** * Create escrow deposit instruction for advanced transaction building * @param {Object} options - Deposit options * @param {string} channel - Channel public key * @param {string} depositor - Depositor's public key * @param {number} amount - Amount to deposit in lamports * @returns {Promise<Object>} Deposit instruction */ async createEscrowInstruction(options, channel, depositor, amount) { // ... existing implementation } } exports.EscrowService = EscrowService; //# sourceMappingURL=escrow.js.map