diff --git a/typescript/.changeset/cyan-llamas-bow.md b/typescript/.changeset/cyan-llamas-bow.md new file mode 100644 index 000000000..1b4da303a --- /dev/null +++ b/typescript/.changeset/cyan-llamas-bow.md @@ -0,0 +1,5 @@ +--- +"create-onchain-agent": patch +--- + +Improved error handling, particulately for missing .env vars in next template diff --git a/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/cdp/prepare-agentkit.ts b/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/cdp/prepare-agentkit.ts index 8291a89a4..27e6ec5d1 100644 --- a/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/cdp/prepare-agentkit.ts +++ b/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/cdp/prepare-agentkit.ts @@ -57,6 +57,12 @@ export async function prepareAgentkitAndWalletProvider(): Promise<{ agentkit: AgentKit; walletProvider: WalletProvider; }> { + if (!process.env.CDP_API_KEY_ID || !process.env.CDP_API_KEY_SECRET) { + throw new Error( + "I need both CDP_API_KEY_ID and CDP_API_KEY_SECRET in your .env file to connect to the Coinbase Developer Platform.", + ); + } + try { let walletDataStr: string | null = null; diff --git a/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/privy/prepare-agentkit.ts b/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/privy/prepare-agentkit.ts index 2653c6332..1295d0550 100644 --- a/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/privy/prepare-agentkit.ts +++ b/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/privy/prepare-agentkit.ts @@ -58,6 +58,12 @@ export async function prepareAgentkitAndWalletProvider(): Promise<{ agentkit: AgentKit; walletProvider: WalletProvider; }> { + if (!process.env.PRIVY_APP_ID || !process.env.PRIVY_APP_SECRET) { + throw new Error( + "I need both PRIVY_APP_ID and PRIVY_APP_SECRET in your .env file to set up your wallet.", + ); + } + try { // Initialize WalletProvider: https://docs.cdp.coinbase.com/agentkit/docs/wallet-management const config: PrivyWalletConfig = { diff --git a/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/smart/prepare-agentkit.ts b/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/smart/prepare-agentkit.ts index d12ee2d90..affce09f8 100644 --- a/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/smart/prepare-agentkit.ts +++ b/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/evm/smart/prepare-agentkit.ts @@ -63,30 +63,35 @@ export async function prepareAgentkitAndWalletProvider(): Promise<{ agentkit: AgentKit; walletProvider: WalletProvider; }> { - try { - let walletData: WalletData | null = null; - let privateKey: Hex | null = null; + if (!process.env.CDP_API_KEY_ID || !process.env.CDP_API_KEY_SECRET) { + throw new Error( + "I need both CDP_API_KEY_ID and CDP_API_KEY_SECRET in your .env file to connect to the Coinbase Developer Platform.", + ); + } + + let walletData: WalletData | null = null; + let privateKey: Hex | null = null; - // Read existing wallet data if available - if (fs.existsSync(WALLET_DATA_FILE)) { - try { - walletData = JSON.parse(fs.readFileSync(WALLET_DATA_FILE, "utf8")) as WalletData; - privateKey = walletData.privateKey; - } catch (error) { - console.error("Error reading wallet data:", error); - // Continue without wallet data - } + // Read existing wallet data if available + if (fs.existsSync(WALLET_DATA_FILE)) { + try { + walletData = JSON.parse(fs.readFileSync(WALLET_DATA_FILE, "utf8")) as WalletData; + privateKey = walletData.privateKey; + } catch (error) { + console.error("Error reading wallet data:", error); } + } - if (!privateKey) { - if (walletData?.smartWalletAddress) { - throw new Error( - `Smart wallet found but no private key provided. Either provide the private key, or delete ${WALLET_DATA_FILE} and try again.`, - ); - } - privateKey = (process.env.PRIVATE_KEY || generatePrivateKey()) as Hex; + if (!privateKey) { + if (walletData?.smartWalletAddress) { + throw new Error( + `I found your smart wallet but can't access your private key. Please either provide the private key in your .env, or delete ${WALLET_DATA_FILE} to create a new wallet.`, + ); } + privateKey = (process.env.PRIVATE_KEY || generatePrivateKey()) as Hex; + } + try { const signer = privateKeyToAccount(privateKey); // Initialize WalletProvider: https://docs.cdp.coinbase.com/agentkit/docs/wallet-management @@ -113,7 +118,7 @@ export async function prepareAgentkitAndWalletProvider(): Promise<{ }); // Save wallet data - const smartWalletAddress = await walletProvider.getAddress(); + const smartWalletAddress = walletProvider.getAddress(); fs.writeFileSync( WALLET_DATA_FILE, JSON.stringify({ diff --git a/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/svm/privy/prepare-agentkit.ts b/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/svm/privy/prepare-agentkit.ts index d013f2ac2..c18205968 100644 --- a/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/svm/privy/prepare-agentkit.ts +++ b/typescript/create-onchain-agent/templates/next/app/api/agent/agentkit/svm/privy/prepare-agentkit.ts @@ -57,6 +57,12 @@ export async function prepareAgentkitAndWalletProvider(): Promise<{ agentkit: AgentKit; walletProvider: WalletProvider; }> { + if (!process.env.PRIVY_APP_ID || !process.env.PRIVY_APP_SECRET) { + throw new Error( + "I need both PRIVY_APP_ID and PRIVY_APP_SECRET in your .env file to set up your wallet.", + ); + } + try { // Initialize WalletProvider: https://docs.cdp.coinbase.com/agentkit/docs/wallet-management const config: PrivyWalletConfig = { diff --git a/typescript/create-onchain-agent/templates/next/app/api/agent/framework/langchain/create-agent.ts b/typescript/create-onchain-agent/templates/next/app/api/agent/framework/langchain/create-agent.ts index 96c82f549..4807e065d 100644 --- a/typescript/create-onchain-agent/templates/next/app/api/agent/framework/langchain/create-agent.ts +++ b/typescript/create-onchain-agent/templates/next/app/api/agent/framework/langchain/create-agent.ts @@ -40,9 +40,13 @@ export async function createAgent(): Promise return agent; } - try { - const { agentkit, walletProvider } = await prepareAgentkitAndWalletProvider(); + if (!process.env.OPENAI_API_KEY) { + throw new Error("I need an OPENAI_API_KEY in your .env file to power my intelligence."); + } + const { agentkit, walletProvider } = await prepareAgentkitAndWalletProvider(); + + try { // Initialize LLM: https://platform.openai.com/docs/models#gpt-4o const llm = new ChatOpenAI({ model: "gpt-4o-mini" }); diff --git a/typescript/create-onchain-agent/templates/next/app/api/agent/framework/langchain/route.ts b/typescript/create-onchain-agent/templates/next/app/api/agent/framework/langchain/route.ts index 238f5b885..5607ffdef 100644 --- a/typescript/create-onchain-agent/templates/next/app/api/agent/framework/langchain/route.ts +++ b/typescript/create-onchain-agent/templates/next/app/api/agent/framework/langchain/route.ts @@ -46,6 +46,11 @@ export async function POST( return NextResponse.json({ response: agentResponse }); } catch (error) { console.error("Error processing request:", error); - return NextResponse.json({ error: "Failed to process message" }); + return NextResponse.json({ + error: + error instanceof Error + ? error.message + : "I'm sorry, I encountered an issue processing your message. Please try again later.", + }); } } diff --git a/typescript/create-onchain-agent/templates/next/app/api/agent/framework/vercel-ai-sdk/create-agent.ts b/typescript/create-onchain-agent/templates/next/app/api/agent/framework/vercel-ai-sdk/create-agent.ts index 7814813c4..381a3b32f 100644 --- a/typescript/create-onchain-agent/templates/next/app/api/agent/framework/vercel-ai-sdk/create-agent.ts +++ b/typescript/create-onchain-agent/templates/next/app/api/agent/framework/vercel-ai-sdk/create-agent.ts @@ -44,12 +44,16 @@ export async function createAgent(): Promise { return agent; } + if (!process.env.OPENAI_API_KEY) { + throw new Error("I need an OPENAI_API_KEY in your .env file to power my intelligence."); + } + + const { agentkit, walletProvider } = await prepareAgentkitAndWalletProvider(); + try { // Initialize LLM: https://platform.openai.com/docs/models#gpt-4o const model = openai("gpt-4o-mini"); - const { agentkit, walletProvider } = await prepareAgentkitAndWalletProvider(); - // Initialize Agent const canUseFaucet = walletProvider.getNetwork().networkId == "base-sepolia"; const faucetMessage = `If you ever need funds, you can request them from the faucet.`; diff --git a/typescript/create-onchain-agent/templates/next/app/api/agent/framework/vercel-ai-sdk/route.ts b/typescript/create-onchain-agent/templates/next/app/api/agent/framework/vercel-ai-sdk/route.ts index 3cd2872de..27a039fde 100644 --- a/typescript/create-onchain-agent/templates/next/app/api/agent/framework/vercel-ai-sdk/route.ts +++ b/typescript/create-onchain-agent/templates/next/app/api/agent/framework/vercel-ai-sdk/route.ts @@ -46,6 +46,11 @@ export async function POST( return NextResponse.json({ response: text }); } catch (error) { console.error("Error processing request:", error); - return NextResponse.json({ error: "Failed to process message" }); + return NextResponse.json({ + error: + error instanceof Error + ? error.message + : "I'm sorry, I encountered an issue processing your message. Please try again later.", + }); } }