The following code presents a ToxiBotClient class that acts as an abstraction for communicating with Toxi Bot via npm package.
import { TelegramClient } from "telegram"; // npm i telegram
import { StringSession } from "telegram/sessions/StringSession.js";
import { input } from "@inquirer/prompts"; // npm i @inquirer/prompts
interface CreateSessionParams {
// format: +1234567890
phoneNumber: string;
// only required if 2FA is enabled
password?: string;
}
interface BuyCommandParams {
tokenMint: string;
// amount of SOL to spend with decimals (e.g. 0.1, 0.5, 1)
buyAmount: number;
}
interface SellCommandParams {
tokenMint: string;
// percentage of balance to sell (e.g. 10, 50, 100)
sellBalancePercentage: number;
}
class ToxiBotClient {
readonly botUsername = '@toxi_solana_bot';
private _botChatId: bigInt.BigInteger | undefined;
private readonly _client: TelegramClient;
constructor(apiId: number, apiHash: string, sessionId: string) {
const session = new StringSession(sessionId);
this._client = new TelegramClient(session, apiId, apiHash, {
connectionRetries: 5,
});
}
async connect() {
if (!this._client.connected) {
await this._client.connect();
}
}
async sendMessageToBot(message: string) {
const chatId = this._botChatId ?? this.botUsername;
const msg = await this._client.sendMessage(chatId, {
message,
});
if (!this._botChatId && msg.chatId) {
this._botChatId = msg.chatId;
}
return msg;
}
async sendBuyCommand(params: BuyCommandParams) {
return this.sendMessageToBot(
`/buy ${params.tokenMint} ${params.buyAmount}`,
);
}
async sendSellCommand(params: SellCommandParams) {
return this.sendMessageToBot(
`/sell ${params.tokenMint} ${params.sellBalancePercentage}%`,
);
}
static async createNewSession(
apiId: number,
apiHash: string,
params: CreateSessionParams,
): Promise<string> {
const session = new StringSession('');
const client = new TelegramClient(session, apiId, apiHash, {
connectionRetries: 5,
});
await client.start({
phoneNumber: params.phoneNumber,
password: params.password
? async () => params.password!
: undefined,
phoneCode: async () => {
const code = await input({
message: `Please enter telegram sign in code sent to ${params.phoneNumber}:`,
required: true,
});
return code;
},
onError: (err) => {
throw err;
},
});
const sessionId = client.session.save() as any as string;
return sessionId;
}
}
Usage Examples
Create a new session and save it for future use
const apiId = 1234567;
const apiHash = '0123456789abcdef0123456789abcdef';
const createSessionParams: CreateSessionParams = {
phoneNumber: '+1234567890',
password: 'password',
}
// Create a new session
const sessionId = await ToxiBotClient.createNewSession(apiId, apiHash, createSessionParams);
console.log('New session created:', sessionId);
// You can then use the session ID to create a new client
const client = new ToxiBotClient(apiId, apiHash, sessionId);
await client.connect();
console.log('Client connected');
Use existing session to create a client and perform a Buy Trade
const apiId = 1234567;
const apiHash = '0123456789abcdef0123456789abcdef';
const sessionId = '1BV1Bv'
// Create a new client and establish a connection
const client = new ToxiBotClient(apiId, apiHash, sessionId);
await client.connect();
// Perform a buy trade
const buyCommandParams: BuyCommandParams = {
// $TRUMP token mint
tokenMint: '6p6xgHyF7AeE6TZkSmFsko444wqoP15icUSqi2jfGiPN',
// Buy 0.1 SOL worth of $TRUMP
buyAmount: 0.1,
}
await client.sendBuyCommand(buyCommandParams);
console.log('Buy trade performed');
Future improvements
As stated earlier, this code is just a demo of how you can integrate Toxi Bot trading capabilities into your application. In the real case scenario, you'd most likely need to modify ToxiBotClient class to fit your application requirements.
For example, one of the various improvements you can think of is adding a method (or even a different class) that will wait till your Buy Trade completes and return a signature (an id) of a transaction. It's not as easy as sending a command, but isn't really complicated either. Each time you make a trade in Toxi Bot - it replies to your message notifying the current status of the submitted transaction. Once the transaction is processed and can be seen in the blockchain, the bot edits the original message with "Transaction Confirmed" textand attaches the solscan link to view that transaction. So all you need to do is:
Wait till the status message is sent by the bot. This can be done by adding an event listener to the TelegramClient instance:
this._client.addEventHandler((event) => {
// here goes your logic to handle incoming messages
}, new NewMessage({
chats: [this.botUsername],
incoming: true,
outgoing: false,
}));
Wait till the status message is edited with the result of submitted transaction:
this._client.addEventHandler((event) => {
// here goes your logic to handle edited messages
}, new EditedMessage({
chats: [this.botUsername],
incoming: true,
outgoing: false,
}))
Parse edited message to retrieve transaction signature (transaction id)
At the end, it's all up to you. There are endless options and opportunities when it comes to creating your own application, so don't hesitate to try something yourself!