Skip to content

Telegram bot integration

Build server-side Telegram bots that give each user a stable on-chain identity and sign transactions with AWS KMS. No browser wallet, no per-tx popups. This guide uses the @0xgasless/core SDK (OxGasServerWallet) with a pattern that maps Telegram user IDs to wallets and optionally enforces policies from the 0xGasless Dashboard.

Idempotent mapping

Map any Telegram ID (for example 123456789) to a permanent EVM address. First call creates the wallet; later calls return the same address.

Non-custodial KMS

Keys are generated and held in AWS KMS. Bot operators never see raw private key material.

Instant signing

Sign on the server in milliseconds, ideal for commands, cron jobs, and automated flows.

Policy guardrails

Use the dashboard for spend limits, contract allowlists, and optional gas sponsorship via a paymaster.

Terminal window
npm install @0xgasless/core

Initialize OxGasServerWallet with your project API key from the 0xGasless Dashboard.

import { OxGasServerWallet } from '@0xgasless/core';
const wallet = new OxGasServerWallet({
apiKey: '0xgas_live_sk_...', // Your project secret key
defaultChainId: 137, // Optional: default chain (e.g. Polygon)
});

Use the Telegram user id as userId. Prefixing (for example tg_${id}) keeps namespaces clear if you reuse the same project elsewhere.

const telegramId = ctx.from.id.toString();
const address = await wallet.getAddress(`tg_${telegramId}`);
console.log(`User ${telegramId} has address ${address}`);

Build calldata and sign server-side. The SDK returns an RLP-encoded raw transaction hex string.

const signResult = await wallet.signTransaction(`tg_${telegramId}`, {
to: '0xTargetContract...',
value: '1000000000000000', // 0.001 native token in wei (string)
chainId: 137,
data: '0x...', // Optional contract call data
});
// signResult.rawTx: signed RLP-encoded hex

Send rawTx through any compatible RPC (public or private).

const { txHash } = await wallet.broadcastTransaction(
signResult.rawTx,
'https://polygon-rpc.com'
);
console.log(`Transaction submitted: ${txHash}`);

Below is a minimal Telegraf bot: /start shows the user’s wallet; /send signs and broadcasts a native transfer on Polygon.

import { Telegraf } from 'telegraf';
import { OxGasServerWallet, PolicyViolationError } from '@0xgasless/core';
const bot = new Telegraf(process.env.BOT_TOKEN);
const sdk = new OxGasServerWallet({ apiKey: process.env.OXGAS_API_KEY });
bot.start(async (ctx) => {
const address = await sdk.getAddress(`tg_${ctx.from.id}`);
ctx.reply(`Welcome! Your permanent bot wallet is:\n\n\`${address}\``, {
parse_mode: 'MarkdownV2',
});
});
bot.command('send', async (ctx) => {
const [_, to, value] = ctx.message.text.split(' ');
const userId = `tg_${ctx.from.id}`;
try {
ctx.reply('⏳ Signing and sending...');
const { rawTx } = await sdk.signTransaction(userId, {
to: to as `0x${string}`,
value: value,
chainId: 137,
});
const { txHash } = await sdk.broadcastTransaction(rawTx, 'https://polygon-rpc.com');
ctx.reply(`✅ Success!\nHash: ${txHash}`);
} catch (err) {
if (err instanceof PolicyViolationError) {
ctx.reply(`❌ Blocked by dashboard policy: ${err.reason}`);
} else {
ctx.reply(`❌ Failed: ${(err as Error).message}`);
}
}
});
bot.launch();

Tune safety and spend from the dashboard:

  1. Spending limits: Cap per-userId spend (for example per day in USD terms, per product configuration).
  2. Allowlists: Restrict calls to your own contract set so the bot cannot be abused to drain to arbitrary addresses.
  3. Gas sponsorship: Optional paymaster so end users do not pay gas (product-dependent).

Wrap SDK calls in try / catch. Common error types:

ClassWhen it happens
WalletNotFoundErrorNo wallet exists yet for the given userId.
PolicyViolationErrorTransaction rejected by dashboard rules.
ServerSigningErrorSigning failed (KMS or invalid transaction params).
NetworkErrorCould not reach the 0xGasless API or the RPC endpoint.