nestai-framework
Version:
Unlocking Next-Gen AI Agents with N.E.S.T.
98 lines (83 loc) • 4.18 kB
text/typescript
import { config } from "dotenv";
import { VersionedTransaction, Connection, Keypair } from "@solana/web3.js";
import bs58 from "bs58";
import fetch from "node-fetch";
import { checkAgentExists } from "../firebase.js";
// Load environment variables from .env file
config();
// Solana RPC endpoint
const RPC_ENDPOINT = process.env.RPC_ENDPOINT || "https://api.mainnet-beta.solana.com";
// Solana connection setup with confirmed commitment level
const web3Connection = new Connection(RPC_ENDPOINT, "confirmed");
/**
* Sends a transaction for the specified agent via a portal.
* This function checks if the agent exists, then retrieves trade details
* from environment variables to construct and send the transaction to the portal.
*
* @param agentName The name of the agent requesting the transaction.
* @throws Throws an error if the private key is not set or is invalid.
*/
async function sendPortalTransaction(agentName: string) {
// Check if the agent exists in the database
const agentExists = await checkAgentExists(agentName);
if (!agentExists) {
console.error(`Error: No agent found with the name "${agentName}".`);
return;
}
// Retrieve trade settings from environment variables
const action = process.env.TRADE_ACTION || "buy"; // Default action is "buy"
const mint = process.env.TRADE_MINT || ""; // Mint address of the token to trade
const amount = parseInt(process.env.TRADE_AMOUNT || "1000"); // Amount to trade (default is 1000)
// Retrieve the secret key from the environment variables (for signing the transaction)
const secretKey = process.env.PK;
if (!secretKey) {
throw new Error("PK is not set in the .env file!");
}
// Decode the base58-encoded secret key
const decodedSecretKey = bs58.decode(secretKey);
// Check if the decoded secret key has the correct length (64 bytes)
if (decodedSecretKey.length !== 64) {
throw new Error("Invalid private key length! Ensure the key is correctly encoded in base58.");
}
// Create a Keypair from the decoded secret key for signing the transaction
const signerKeyPair = Keypair.fromSecretKey(decodedSecretKey);
// Make a POST request to the external portal API with the trade details
const response = await fetch("https://pumpportal.fun/api/trade-local", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
publicKey: signerKeyPair.publicKey.toBase58(), // The public key of the signer
action: action, // Action to perform ("buy" or "sell")
mint: mint, // Mint address of the token
denominatedInSol: "false", // Whether the amount is denominated in SOL (false by default)
amount: amount, // Amount to trade
slippage: 10, // Slippage tolerance (10% by default)
priorityFee: 0.00001, // Priority fee for transaction (set by default)
pool: "pump", // The liquidity pool to interact with (set to "pump")
}),
});
// If the response is successful (HTTP 200), deserialize the transaction and send it
if (response.status === 200) {
const data = await response.arrayBuffer(); // Get the transaction data as ArrayBuffer
const tx = VersionedTransaction.deserialize(new Uint8Array(data)); // Deserialize the transaction
// Sign the transaction with the private key and send it to the network
tx.sign([signerKeyPair]);
const signature = await web3Connection.sendTransaction(tx);
console.log(`Transaction successful: https://solscan.io/tx/${signature}`);
} else {
console.error("Error:", response.statusText); // Log an error if the response is not successful
}
}
// Retrieve the agent name from command-line arguments
const agentName = process.argv[2];
// Ensure the agent name is provided as an argument
if (!agentName) {
console.error("Error: Please provide the agent name as an argument.");
process.exit(1);
}
// Call the function to send the portal transaction and catch any errors
sendPortalTransaction(agentName).catch((error) => {
console.error("An error occurred:", error);
});