UNPKG

@pod-protocol/sdk

Version:

TypeScript SDK for PoD Protocol - AI agent communication on Solana

164 lines (161 loc) 7.53 kB
import { g as generateKeyPairSigner } from '../index.node-MFRNpwTP.js'; import * as anchor from '@coral-xyz/anchor'; import { B as BaseService } from '../base-D1CgLXYS.js'; import { findAgentPDA, retry, getAccountLastUpdated } from '../utils.esm.js'; import '../types-CllXlTfL.js'; import 'node:events'; import 'ws'; const { BN, AnchorProvider, Program } = anchor; /** * Agent-related operations service */ class AgentService extends BaseService { async registerAgent(wallet, options) { const [agentPDA] = await findAgentPDA(wallet.address, this.programId); return retry(async () => { // Always prefer using the pre-initialized program if available let program; if (this.program) { // Program was pre-initialized with the wallet - use it directly program = this.program; } else { // This should not happen if client.initialize(wallet) was called properly throw new Error("No program instance available. Ensure client.initialize(wallet) was called successfully."); } try { const tx = await program.methods .registerAgent(new BN(options.capabilities), options.metadataUri) .accounts({ agentAccount: agentPDA, signer: wallet.address, systemProgram: "11111111111111111111111111111112", // System Program ID }) .rpc(); return tx; } catch (error) { // Provide more specific error messages const errorMessage = error instanceof Error ? error.message : String(error); if (errorMessage?.includes("Account does not exist")) { throw new Error("Program account not found. Verify the program is deployed and the program ID is correct."); } if (errorMessage?.includes("insufficient funds")) { throw new Error("Insufficient SOL balance to pay for transaction fees and rent."); } if (errorMessage?.includes("custom program error")) { throw new Error(`Program error: ${errorMessage}. Check program logs for details.`); } throw new Error(`Agent registration failed: ${errorMessage}`); } }); } async updateAgent(wallet, options) { const [agentPDA] = await findAgentPDA(wallet.address, this.programId); return retry(async () => { // Use the program if it was initialized with a wallet, otherwise create a fresh one let program; if (this.program) { // Program was pre-initialized with the wallet program = this.program; } else { // Fallback: create a fresh provider with the actual wallet for this transaction const provider = new AnchorProvider(this.rpc, wallet, { commitment: this.commitment, skipPreflight: true, }); // Get the IDL directly (no dummy wallet involved) const idl = this.ensureIDL(); // Create a new program instance with the proper wallet program = new Program(idl, provider); } const tx = await program.methods .updateAgent(options.capabilities !== undefined ? new BN(options.capabilities) : null, options.metadataUri !== undefined ? options.metadataUri : null) .accounts({ agentAccount: agentPDA, signer: wallet.address, }) .rpc(); return tx; }); } async getAgent(walletAddress) { const [agentPDA] = await findAgentPDA(walletAddress, this.programId); try { // Use the program if it was initialized, otherwise create a temporary one let program; if (this.program) { // Program was pre-initialized, use it program = this.program; } else { // For read operations, use a read-only provider without wallet const tempKeyPairSigner = await generateKeyPairSigner(); const readOnlyWallet = { publicKey: tempKeyPairSigner.address, signTransaction: async () => { throw new Error('Read-only wallet'); }, signAllTransactions: async () => { throw new Error('Read-only wallet'); }, payer: {} // Add missing payer property }; const readOnlyProvider = new AnchorProvider(this.rpc, readOnlyWallet, { commitment: 'confirmed' }); const idl = this.ensureIDL(); program = new Program(idl, readOnlyProvider); } // eslint-disable-next-line no-unused-vars const agentAccount = program.account.agentAccount; const account = await agentAccount.fetch(agentPDA); return { pubkey: agentPDA, capabilities: account.capabilities.toNumber(), metadataUri: account.metadataUri, reputation: account.reputation?.toNumber() || 0, lastUpdated: getAccountLastUpdated(account), invitesSent: account.invitesSent?.toNumber() || 0, lastInviteAt: account.lastInviteAt?.toNumber() || 0, bump: account.bump, }; } catch (error) { if (error instanceof Error && error.message?.includes("Account does not exist")) { return null; } throw error; } } async getAllAgents(limit = 100) { try { // For read operations, use a read-only provider without wallet const tempKeyPairSigner = await generateKeyPairSigner(); const readOnlyWallet = { publicKey: tempKeyPairSigner.address, signTransaction: async () => { throw new Error('Read-only wallet'); }, signAllTransactions: async () => { throw new Error('Read-only wallet'); }, payer: {} // Add missing payer property }; const readOnlyProvider = new AnchorProvider(this.rpc, readOnlyWallet, { commitment: 'confirmed' }); const idl = this.ensureIDL(); const program = new Program(idl, readOnlyProvider); const agentAccount = program.account.agentAccount; const accounts = await agentAccount.all(); return accounts.slice(0, limit).map((acc) => ({ pubkey: acc.publicKey, capabilities: acc.account.capabilities.toNumber(), metadataUri: acc.account.metadataUri, reputation: acc.account.reputation?.toNumber() || 0, lastUpdated: getAccountLastUpdated(acc.account), invitesSent: 0, lastInviteAt: 0, bump: acc.account.bump, })); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); throw new Error(`Failed to fetch agents: ${errorMessage}`); } } } export { AgentService }; //# sourceMappingURL=agent.esm.js.map