This solutions guide explains how to create a Telegram trading bot using the Coinbase Developer Platform (CDP) SDK and Wallet API. The bot will allow users to check balances, deposit and withdraw ETH, and perform buy and sell operations directly from Telegram.
This is a great template for building your own Telegram bot with additional features from the CDP SDK, such as deploying tokens or interacting with smart contracts!
Replit for easy deployment
Replit is an AI-powered software development & deployment platform for building, sharing, and shipping software fast. Coinbase has partnered with Replit to create a template that enables developers to register their AI agent onchain in just minutes.
Use the Replit template for an easier cloning and deployment experience.
First, we need to import the necessary modules for our bot. This includes the grammy library for interacting with Telegram, the coinbase-sdk for interacting with the CDK SDK, and other utility libraries.
Next, we ensure that all required environment variables are set. These variables include the Telegram bot token, Coinbase secret API key name and secret, and the encryption key.
index.js
Copy
Ask AI
// Ensure environment variables are set.const requiredEnvVars = [ "TELEGRAM_BOT_TOKEN", "COINBASE_API_KEY_NAME", "COINBASE_API_KEY_SECRET", "ENCRYPTION_KEY",];requiredEnvVars.forEach((env) => { if (!process.env[env]) { throw new Error(`missing ${env} environment variable`); }});
We create a bot object using the grammy library and set up in-memory storage for user states and a database for storing wallets.
index.js
Copy
Ask AI
// Create a bot objectconst bot = new Bot(process.env.TELEGRAM_BOT_TOKEN);// In-memory storage for user statesconst userStates = {};// Database for storing walletsconst db = new Database();
We define a function to handle deposits. This function provides the user with their address and instructions for depositing ETH.
index.js
Copy
Ask AI
// Handle depositsasync function handleDeposit(ctx) { const userAddress = await getOrCreateAddress(ctx.from); await sendReply( ctx, "_Note: As this is a test app, make sure to deposit only small amounts of ETH!_", { parse_mode: "Markdown" }, ); await sendReply( ctx, "Please send your ETH to the following address on Base:", ); await sendReply(ctx, `${userAddress.getId()}`, { parse_mode: "Markdown" });}
We define a function to handle the initial withdrawal request. This function prompts the user to enter the amount of ETH they want to withdraw.
index.js
Copy
Ask AI
// Handle initial withdrawal requestasync function handleInitialWithdrawal(ctx) { updateUserState(ctx.from, { withdrawalRequested: true }); await sendReply( ctx, "Please respond with the amount of ETH you want to withdraw.", { reply_markup: { force_reply: true } }, );}
We define functions to handle buy requests. These functions prompt the user to enter the asset they want to buy and the amount of ETH they want to spend.
index.js
Copy
Ask AI
// Handle buy requestasync function handleInitialBuy(ctx) { await handleTradeInit(ctx, "buy");}// Handle buysasync function handleBuy(ctx) { await executeTrade(ctx, "buy");}
We define functions to initialize and execute trades. These functions handle the user input and perform the trade operations.
index.js
Copy
Ask AI
// Initialize trade (Buy/Sell)async function handleTradeInit(ctx, type) { const prompt = type === "buy" ? "Please respond with the asset you would like to buy (ticker or contract address)." : "Please respond with the asset you would like to sell (ticker or contract address)."; updateUserState(ctx.from, { [`${type}Requested`]: true }); await sendReply(ctx, prompt, { reply_markup: { force_reply: true } });}// Generalized function to execute tradesasync function executeTrade(ctx, type) { const userState = userStates[ctx.from.id] || {}; if (!userState.asset) { // Prevent sale of ETH and log asset to user state if (ctx.message.text.toLowerCase() === "eth" && type === "sell") { await ctx.reply( "You cannot sell ETH, as it is the quote currency. Please try again.", ); clearUserState(ctx.from); return; } updateUserState(ctx.from, { asset: ctx.message.text.toLowerCase() }); const prompt = type === "buy" ? "Please respond with the amount of ETH you would like to spend." : "Please respond with the amount of the asset you would like to sell."; await sendReply(ctx, prompt, { reply_markup: { force_reply: true } }); } else { const amount = new Decimal(parseFloat(ctx.message.text)); const userAddress = await getOrCreateAddress(ctx.from); const currentBalance = await userAddress.getBalance( type === "buy" ? Coinbase.assets.Eth : userState.asset, ); if (amount.isNaN() || amount.greaterThan(currentBalance)) { await ctx.reply( "Invalid amount or insufficient balance. Please try again.", ); clearUserState(ctx.from); } else { const tradeType = type === "buy" ? { fromAssetId: Coinbase.assets.Eth, toAssetId: userState.asset } : { fromAssetId: userState.asset, toAssetId: Coinbase.assets.Eth }; await sendReply(ctx, `Initiating ${type}...`); try { const userAddress = await getOrCreateAddress(ctx.from); const trade = await userAddress.createTrade({ amount, ...tradeType }); await trade.wait(); await sendReply( ctx, `Successfully completed ${type}: [Basescan Link](${trade.getTransaction().getTransactionLink()})`, { parse_mode: "Markdown" }, ); clearUserState(ctx.from); } catch (error) { await ctx.reply(`An error occurred while initiating the ${type}.`); console.error(error); clearUserState(ctx.from); } } }}
We define a function to handle exporting the key. This function provides the user with their private key and instructions for storing it safely.
index.js
Copy
Ask AI
// Handle exporting the keyasync function handleExportKey(ctx) { const userAddress = await getOrCreateAddress(ctx.from); const privateKey = userAddress.export(); await sendReply( ctx, "Your private key will be in the next message. Do NOT share it with anyone, and make sure you store it in a safe place.", ); await sendReply(ctx, privateKey);}
Now that you have set up your Telegram trading bot, you can interact with it by sending commands and messages. The bot will handle checking balances, deposits, withdrawals, and trading operations. If you have any questions or need further assistance, feel free to reach out to us in the CDP Discord.