Server-side wallet
For bots, market-makers, and back-end services that hold their own keys. Same API, different broadcast path.
Install
bash
npm install @ton/ton @ton/core @ton/cryptoBuild the wallet
wallet.ts
import { TonClient4, WalletContractV4 } from '@ton/ton';
import { mnemonicToWalletKey } from '@ton/crypto';
const client = new TonClient4({
endpoint: 'https://mainnet-v4.tonhubapi.com',
});
const key = await mnemonicToWalletKey(MNEMONIC.split(' '));
const wallet = WalletContractV4.create({
workchain: 0,
publicKey: key.publicKey,
});
const opened = client.open(wallet);Quote and broadcast
ts
import { internal, Cell } from '@ton/core';
// 1. Get the tx body from chop
const tx = await fetch('https://chop.ag/api/v1/tx', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
assetIn: 'TON',
assetOut: USDT_MASTER,
amountIn: '1000000000', // 1 TON
slippageBps: 100,
userAddress: wallet.address.toString(),
}),
}).then((r) => r.json());
// 2. Convert chop's messages into ton-core internal messages
const messages = tx.messages.map((m) =>
internal({
to: m.to,
value: BigInt(m.value),
body: Cell.fromBase64(m.bodyBoc),
bounce: true,
})
);
// 3. Sign and send via the wallet contract
const seqno = await opened.getSeqno();
await opened.sendTransfer({
seqno,
secretKey: key.secretKey,
messages,
});
// 4. Wait for confirmation by polling seqno
while ((await opened.getSeqno()) === seqno) {
await new Promise((r) => setTimeout(r, 2000));
}Multi-message support
Wallet v4 supports up to 4 outgoing messages. Wallet v5 supports many more. Your wallet version must supporttx.messages.length — otherwise sendTransferwill throw.
Verifying actual fills
After the seqno advances, query the user’s Jetton wallet balance for the output asset. The DeDust SDK has a clean helper:
ts
import { JettonRoot } from '@dedust/sdk';
const root = client.open(JettonRoot.createFromAddress(USDT_MASTER));
const userJW = client.open(await root.getWallet(wallet.address));
const balance = await userJW.getBalance();For multi-hop swaps, allow ~10–15 seconds after the wallet seqno advance — the second pool hop runs as a forwarded message and lands in the next block.
Self-hosting the API
chop’s API server is a thin Express wrapper around the aggregator library. If you don’t want to depend on chop.ag for availability, you can run it yourself — same code, same endpoints:
bash
git clone https://github.com/your-org/ton_aggregator
cd ton_aggregator
npm install
npm run serve # listens on :3000