@ton/mcp 0.1.15-alpha.10 → 0.1.15-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,7 +26,7 @@ Choose one control path per task: either run `@ton/mcp` as an MCP server (stdio
26
26
 
27
27
  Self-custody wallets for autonomous agents. Your AI agent gets TON wallet capabilities — transfers, swaps, NFTs. User keeps the master key, agent keeps the operator key.
28
28
 
29
- **Learn more about [Agentic Wallets](https://agentic-wallets-dashboard.vercel.app/).**
29
+ **Learn more about [Agentic Wallets](https://agents.ton.org/).**
30
30
 
31
31
  Agentic Wallets mode is the default mode that allows you to manage agentic wallets. To create your first agentic wallet, ask your agent to `create agentic wallet` and follow the instructions.
32
32
 
package/dist/cli.js CHANGED
@@ -133560,7 +133560,7 @@ async function createMcpWalletServiceFromStoredWallet(input) {
133560
133560
  * LICENSE file in the root directory of this source tree.
133561
133561
  *
133562
133562
  */
133563
- const AGENTIC_DASHBOARD_BASE_URL = "https://agentic-wallets-dashboard.vercel.app/";
133563
+ const AGENTIC_DASHBOARD_BASE_URL = "https://agents.ton.org/";
133564
133564
  const AGENTIC_LOOKUP_RETRY_ATTEMPTS = 5;
133565
133565
  const AGENTIC_LOOKUP_RETRY_DELAY_MS = 1500;
133566
133566
  const AGENTIC_WALLET_CODE_HASH = AgenticWalletCodeCell.hash().toString("hex");
@@ -135164,7 +135164,7 @@ const getNftsByAddressSchema = objectType({
135164
135164
  limit: numberType().min(1).max(100).optional().describe("Maximum number of NFTs to return (default: 20, max: 100)"),
135165
135165
  offset: numberType().min(0).optional().describe("Offset for pagination (default: 0)")
135166
135166
  });
135167
- const getJettonInfoSchema = objectType({ address: stringType().min(1).describe("Jetton master contract address") });
135167
+ const getJettonInfoSchema = objectType({ jettonAddress: stringType().min(1).describe("Jetton master contract address") });
135168
135168
  objectType({
135169
135169
  jettonAddress: stringType().min(1).describe("Jetton master contract address"),
135170
135170
  ownerAddress: stringType().min(1).describe("Owner wallet address")
@@ -135287,7 +135287,7 @@ function createMcpAddressTools(service) {
135287
135287
  inputSchema: getJettonInfoSchema,
135288
135288
  handler: async (args) => {
135289
135289
  try {
135290
- const jettonInfo = await service.getJettonInfo(args.address);
135290
+ const jettonInfo = await service.getJettonInfo(args.jettonAddress);
135291
135291
  if (!jettonInfo) return {
135292
135292
  content: [{
135293
135293
  type: "text",
@@ -137211,8 +137211,43 @@ if (WALLET_VERSION !== "agentic" && WALLET_VERSION !== "v4r2" && WALLET_VERSION
137211
137211
  function log(message) {
137212
137212
  console.error(`[${SERVER_NAME}] ${message}`);
137213
137213
  }
137214
+ function printHelp() {
137215
+ const help = `
137216
+ @ton/mcp – TON wallet MCP server & CLI
137217
+
137218
+ Usage:
137219
+ npx @ton/mcp@alpha stdio MCP server (default)
137220
+ npx @ton/mcp@alpha --http [port] HTTP MCP server (default: 0.0.0.0:3000)
137221
+ npx @ton/mcp@alpha --http --host 127.0.0.1 HTTP server on custom host
137222
+ npx @ton/mcp@alpha <tool_name> [--arg value] call one tool and exit
137223
+
137224
+ Options:
137225
+ --help, -h Show this help message
137226
+ --http [port] Start HTTP server instead of stdio
137227
+ --host <addr> Bind HTTP server to address (default: 0.0.0.0)
137228
+
137229
+ Examples:
137230
+ npx @ton/mcp@alpha get_balance
137231
+ npx @ton/mcp@alpha get_jetton_balance --jettonAddress EQAbc...
137232
+ npx @ton/mcp@alpha get_swap_quote --fromToken TON --toToken EQAbc... --amount 1
137233
+ npx @ton/mcp@alpha send_ton --toAddress UQA... --amount 0.5
137234
+
137235
+ Environment variables:
137236
+ NETWORK mainnet (default) or testnet
137237
+ MNEMONIC 24-word mnemonic phrase
137238
+ PRIVATE_KEY Hex-encoded private key (alternative to MNEMONIC)
137239
+ WALLET_VERSION v5r1 (default), v4r2, or agentic
137240
+ TONCENTER_API_KEY Optional Toncenter API key
137241
+ TON_CONFIG_PATH Config file path (default: ~/.config/ton/config.json)
137242
+ `.trimStart();
137243
+ process.stdout.write(help);
137244
+ }
137214
137245
  function parseArgs() {
137215
137246
  const args = process.argv.slice(2);
137247
+ if (args.includes("--help") || args.includes("-h")) {
137248
+ printHelp();
137249
+ process.exit(0);
137250
+ }
137216
137251
  const httpIndex = args.indexOf("--http");
137217
137252
  if (httpIndex !== -1) {
137218
137253
  const nextArg = args[httpIndex + 1];
package/dist/index.cjs CHANGED
@@ -132755,7 +132755,7 @@ async function createMcpWalletServiceFromStoredWallet(input) {
132755
132755
  * LICENSE file in the root directory of this source tree.
132756
132756
  *
132757
132757
  */
132758
- const AGENTIC_DASHBOARD_BASE_URL = "https://agentic-wallets-dashboard.vercel.app/";
132758
+ const AGENTIC_DASHBOARD_BASE_URL = "https://agents.ton.org/";
132759
132759
  const AGENTIC_LOOKUP_RETRY_ATTEMPTS = 5;
132760
132760
  const AGENTIC_LOOKUP_RETRY_DELAY_MS = 1500;
132761
132761
  const AGENTIC_WALLET_CODE_HASH = AgenticWalletCodeCell.hash().toString("hex");
@@ -134359,7 +134359,7 @@ const getNftsByAddressSchema = objectType({
134359
134359
  limit: numberType().min(1).max(100).optional().describe("Maximum number of NFTs to return (default: 20, max: 100)"),
134360
134360
  offset: numberType().min(0).optional().describe("Offset for pagination (default: 0)")
134361
134361
  });
134362
- const getJettonInfoSchema = objectType({ address: stringType().min(1).describe("Jetton master contract address") });
134362
+ const getJettonInfoSchema = objectType({ jettonAddress: stringType().min(1).describe("Jetton master contract address") });
134363
134363
  objectType({
134364
134364
  jettonAddress: stringType().min(1).describe("Jetton master contract address"),
134365
134365
  ownerAddress: stringType().min(1).describe("Owner wallet address")
@@ -134482,7 +134482,7 @@ function createMcpAddressTools(service) {
134482
134482
  inputSchema: getJettonInfoSchema,
134483
134483
  handler: async (args) => {
134484
134484
  try {
134485
- const jettonInfo = await service.getJettonInfo(args.address);
134485
+ const jettonInfo = await service.getJettonInfo(args.jettonAddress);
134486
134486
  if (!jettonInfo) return {
134487
134487
  content: [{
134488
134488
  type: "text",
package/dist/index.js CHANGED
@@ -132755,7 +132755,7 @@ async function createMcpWalletServiceFromStoredWallet(input) {
132755
132755
  * LICENSE file in the root directory of this source tree.
132756
132756
  *
132757
132757
  */
132758
- const AGENTIC_DASHBOARD_BASE_URL = "https://agentic-wallets-dashboard.vercel.app/";
132758
+ const AGENTIC_DASHBOARD_BASE_URL = "https://agents.ton.org/";
132759
132759
  const AGENTIC_LOOKUP_RETRY_ATTEMPTS = 5;
132760
132760
  const AGENTIC_LOOKUP_RETRY_DELAY_MS = 1500;
132761
132761
  const AGENTIC_WALLET_CODE_HASH = AgenticWalletCodeCell.hash().toString("hex");
@@ -134359,7 +134359,7 @@ const getNftsByAddressSchema = objectType({
134359
134359
  limit: numberType().min(1).max(100).optional().describe("Maximum number of NFTs to return (default: 20, max: 100)"),
134360
134360
  offset: numberType().min(0).optional().describe("Offset for pagination (default: 0)")
134361
134361
  });
134362
- const getJettonInfoSchema = objectType({ address: stringType().min(1).describe("Jetton master contract address") });
134362
+ const getJettonInfoSchema = objectType({ jettonAddress: stringType().min(1).describe("Jetton master contract address") });
134363
134363
  objectType({
134364
134364
  jettonAddress: stringType().min(1).describe("Jetton master contract address"),
134365
134365
  ownerAddress: stringType().min(1).describe("Owner wallet address")
@@ -134482,7 +134482,7 @@ function createMcpAddressTools(service) {
134482
134482
  inputSchema: getJettonInfoSchema,
134483
134483
  handler: async (args) => {
134484
134484
  try {
134485
- const jettonInfo = await service.getJettonInfo(args.address);
134485
+ const jettonInfo = await service.getJettonInfo(args.jettonAddress);
134486
134486
  if (!jettonInfo) return {
134487
134487
  content: [{
134488
134488
  type: "text",
@@ -133824,7 +133824,7 @@ async function createMcpWalletServiceFromStoredWallet(input) {
133824
133824
  * LICENSE file in the root directory of this source tree.
133825
133825
  *
133826
133826
  */
133827
- const AGENTIC_DASHBOARD_BASE_URL = "https://agentic-wallets-dashboard.vercel.app/";
133827
+ const AGENTIC_DASHBOARD_BASE_URL = "https://agents.ton.org/";
133828
133828
  const AGENTIC_LOOKUP_RETRY_ATTEMPTS = 5;
133829
133829
  const AGENTIC_LOOKUP_RETRY_DELAY_MS = 1500;
133830
133830
  const AGENTIC_WALLET_CODE_HASH = AgenticWalletCodeCell.hash().toString("hex");
@@ -135428,7 +135428,7 @@ const getNftsByAddressSchema = objectType({
135428
135428
  limit: numberType().min(1).max(100).optional().describe("Maximum number of NFTs to return (default: 20, max: 100)"),
135429
135429
  offset: numberType().min(0).optional().describe("Offset for pagination (default: 0)")
135430
135430
  });
135431
- const getJettonInfoSchema = objectType({ address: stringType().min(1).describe("Jetton master contract address") });
135431
+ const getJettonInfoSchema = objectType({ jettonAddress: stringType().min(1).describe("Jetton master contract address") });
135432
135432
  objectType({
135433
135433
  jettonAddress: stringType().min(1).describe("Jetton master contract address"),
135434
135434
  ownerAddress: stringType().min(1).describe("Owner wallet address")
@@ -135551,7 +135551,7 @@ function createMcpAddressTools(service) {
135551
135551
  inputSchema: getJettonInfoSchema,
135552
135552
  handler: async (args) => {
135553
135553
  try {
135554
- const jettonInfo = await service.getJettonInfo(args.address);
135554
+ const jettonInfo = await service.getJettonInfo(args.jettonAddress);
135555
135555
  if (!jettonInfo) return {
135556
135556
  content: [{
135557
135557
  type: "text",
@@ -133824,7 +133824,7 @@ async function createMcpWalletServiceFromStoredWallet(input) {
133824
133824
  * LICENSE file in the root directory of this source tree.
133825
133825
  *
133826
133826
  */
133827
- const AGENTIC_DASHBOARD_BASE_URL = "https://agentic-wallets-dashboard.vercel.app/";
133827
+ const AGENTIC_DASHBOARD_BASE_URL = "https://agents.ton.org/";
133828
133828
  const AGENTIC_LOOKUP_RETRY_ATTEMPTS = 5;
133829
133829
  const AGENTIC_LOOKUP_RETRY_DELAY_MS = 1500;
133830
133830
  const AGENTIC_WALLET_CODE_HASH = AgenticWalletCodeCell.hash().toString("hex");
@@ -135428,7 +135428,7 @@ const getNftsByAddressSchema = objectType({
135428
135428
  limit: numberType().min(1).max(100).optional().describe("Maximum number of NFTs to return (default: 20, max: 100)"),
135429
135429
  offset: numberType().min(0).optional().describe("Offset for pagination (default: 0)")
135430
135430
  });
135431
- const getJettonInfoSchema = objectType({ address: stringType().min(1).describe("Jetton master contract address") });
135431
+ const getJettonInfoSchema = objectType({ jettonAddress: stringType().min(1).describe("Jetton master contract address") });
135432
135432
  objectType({
135433
135433
  jettonAddress: stringType().min(1).describe("Jetton master contract address"),
135434
135434
  ownerAddress: stringType().min(1).describe("Owner wallet address")
@@ -135551,7 +135551,7 @@ function createMcpAddressTools(service) {
135551
135551
  inputSchema: getJettonInfoSchema,
135552
135552
  handler: async (args) => {
135553
135553
  try {
135554
- const jettonInfo = await service.getJettonInfo(args.address);
135554
+ const jettonInfo = await service.getJettonInfo(args.jettonAddress);
135555
135555
  if (!jettonInfo) return {
135556
135556
  content: [{
135557
135557
  type: "text",
@@ -42,11 +42,11 @@ export declare const getNftsByAddressSchema: z.ZodObject<{
42
42
  offset?: number | undefined;
43
43
  }>;
44
44
  export declare const getJettonInfoSchema: z.ZodObject<{
45
- address: z.ZodString;
45
+ jettonAddress: z.ZodString;
46
46
  }, "strip", z.ZodTypeAny, {
47
- address: string;
47
+ jettonAddress: string;
48
48
  }, {
49
- address: string;
49
+ jettonAddress: string;
50
50
  }>;
51
51
  export declare const getJettonWalletAddressSchema: z.ZodObject<{
52
52
  jettonAddress: z.ZodString;
@@ -107,11 +107,11 @@ export declare function createMcpAddressTools(service: McpWalletService): {
107
107
  get_jetton_info: {
108
108
  description: string;
109
109
  inputSchema: z.ZodObject<{
110
- address: z.ZodString;
110
+ jettonAddress: z.ZodString;
111
111
  }, "strip", z.ZodTypeAny, {
112
- address: string;
112
+ jettonAddress: string;
113
113
  }, {
114
- address: string;
114
+ jettonAddress: string;
115
115
  }>;
116
116
  handler: (args: z.infer<typeof getJettonInfoSchema>) => Promise<ToolResponse>;
117
117
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ton/mcp",
3
- "version": "0.1.15-alpha.10",
3
+ "version": "0.1.15-alpha.12",
4
4
  "description": "TON MCP Server - Model Context Protocol server for TON blockchain wallet operations",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -15,11 +15,11 @@ Read-only queries for wallet balances, token holdings, and transaction history o
15
15
  | ---- | -------- | -------- |
16
16
  | `get_wallet` | — | `walletSelector` |
17
17
  | `get_balance` | — | `walletSelector` |
18
- | `get_balance_by_address` | `address` | |
18
+ | `get_balance_by_address` | `address` | `walletSelector` |
19
19
  | `get_jetton_balance` | `jettonAddress` | `walletSelector` |
20
20
  | `get_jettons` | — | `walletSelector` |
21
- | `get_jettons_by_address` | `address` | |
22
- | `get_jetton_info` | `address` | |
21
+ | `get_jettons_by_address` | `address` | `limit`, `offset`, `walletSelector` |
22
+ | `get_jetton_info` | `jettonAddress` | `walletSelector` |
23
23
  | `get_known_jettons` | — | — |
24
24
  | `get_transactions` | — | `limit`, `walletSelector` |
25
25
  | `get_transaction_status` | `normalizedHash` | `walletSelector` |
@@ -70,11 +70,11 @@ Without `MNEMONIC` or `PRIVATE_KEY`, the CLI uses the local config registry at `
70
70
  | ---- | ------------- | ------------- |
71
71
  | `get_wallet` | — | `--walletSelector` |
72
72
  | `get_balance` | — | `--walletSelector` |
73
- | `get_balance_by_address` | `--address` | |
73
+ | `get_balance_by_address` | `--address` | `--walletSelector` |
74
74
  | `get_jetton_balance` | `--jettonAddress` | `--walletSelector` |
75
75
  | `get_jettons` | — | `--walletSelector` |
76
- | `get_jettons_by_address` | `--address` | |
77
- | `get_jetton_info` | `--jettonAddress` | |
76
+ | `get_jettons_by_address` | `--address` | `--limit`, `--offset`, `--walletSelector` |
77
+ | `get_jetton_info` | `--jettonAddress` | `--walletSelector` |
78
78
  | `get_transactions` | — | `--limit`, `--walletSelector` |
79
79
  | `get_transaction_status` | `--normalizedHash` | `--walletSelector` |
80
80
  | `get_known_jettons` | — | — |
@@ -95,29 +95,29 @@ Without `MNEMONIC` or `PRIVATE_KEY`, the CLI uses the local config registry at `
95
95
  | `send_ton` | `--toAddress`, `--amount` | `--comment`, `--walletSelector` |
96
96
  | `send_jetton` | `--toAddress`, `--jettonAddress`, `--amount` | `--comment`, `--walletSelector` |
97
97
  | `send_nft` | `--nftAddress`, `--toAddress` | `--comment`, `--walletSelector` |
98
- | `send_raw_transaction` | `--messages` | `--walletSelector` |
99
- | `emulate_transaction` | `--messages` | `--validUntil` |
98
+ | `send_raw_transaction` | `--messages` | `--validUntil`, `--fromAddress`, `--walletSelector` |
99
+ | `emulate_transaction` | `--messages` | `--validUntil`, `--walletSelector` |
100
100
 
101
101
  ### Swaps
102
102
 
103
103
  | Tool | Required args | Optional args |
104
104
  | ---- | ------------- | ------------- |
105
- | `get_swap_quote` | `--fromToken`, `--toToken`, `--amount` | `--walletSelector` |
105
+ | `get_swap_quote` | `--fromToken`, `--toToken`, `--amount` | `--slippageBps`, `--walletSelector` |
106
106
 
107
107
  ### NFTs
108
108
 
109
109
  | Tool | Required args | Optional args |
110
110
  | ---- | ------------- | ------------- |
111
111
  | `get_nfts` | — | `--limit`, `--offset`, `--walletSelector` |
112
- | `get_nfts_by_address` | `--address` | `--limit`, `--offset` |
113
- | `get_nft` | `--nftAddress` | |
112
+ | `get_nfts_by_address` | `--address` | `--limit`, `--offset`, `--walletSelector` |
113
+ | `get_nft` | `--nftAddress` | `--walletSelector` |
114
114
 
115
115
  ### DNS
116
116
 
117
- | Tool | Required args |
118
- | ---- | ------------- |
119
- | `resolve_dns` | `--domain` |
120
- | `back_resolve_dns` | `--address` |
117
+ | Tool | Required args | Optional args |
118
+ | ---- | ------------- | ------------- |
119
+ | `resolve_dns` | `--domain` | `--walletSelector` |
120
+ | `back_resolve_dns` | `--address` | `--walletSelector` |
121
121
 
122
122
  ## Example Session
123
123
 
@@ -135,7 +135,7 @@ npx @ton/mcp@alpha get_jettons
135
135
  npx @ton/mcp@alpha get_transactions --limit 10
136
136
 
137
137
  # Get balance of a specific jetton
138
- npx @ton/mcp@alpha get_jetton_balance --address EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs
138
+ npx @ton/mcp@alpha get_jetton_balance --jettonAddress EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs
139
139
 
140
140
  # Resolve a .ton domain
141
141
  npx @ton/mcp@alpha resolve_dns --domain foundation.ton
@@ -42,7 +42,7 @@ Deploy an on-chain agentic wallet on TON. The agent generates operator keys, ope
42
42
  - The agent keeps the **operator private key** — it can sign transactions autonomously
43
43
  - The user keeps the **owner key** — they can withdraw funds or revoke access at any time
44
44
  - The wallet is an on-chain smart contract (NFT-based), not a custodial service
45
- - The dashboard is at `agentic-wallets-dashboard.vercel.app`
45
+ - The dashboard is at `agents.ton.org`
46
46
 
47
47
  ## Environment Variables
48
48
 
@@ -21,15 +21,17 @@ Backed **xStocks** are jettons on TON. Resolve the **jetton master** from the pu
21
21
 
22
22
  ## Resolve the TON jetton master for an xStock
23
23
 
24
- 1. **By symbol** (e.g. `TSLAx`): fetch
25
- `GET https://api.xstocks.fi/api/v2/public/assets/{symbol}`
24
+ 1. **By symbol** (e.g. `TSLAx`): fetch via **`curl`** (not WebFetch — the xStocks API returns 403 for non-standard user-agents):
25
+ ```bash
26
+ curl -s "https://api.xstocks.fi/api/v2/public/assets/{symbol}"
27
+ ```
26
28
  (production base: `https://api.xstocks.fi/api/v2` — see [xStocks API](https://docs.xstocks.fi/apis/openapi)).
27
29
 
28
30
  2. In the JSON, find `deployments[]` where **`network` is `"Ton"`**. Use that object's **`address`** as the jetton master for MCP (`fromToken` / `toToken`).
29
31
 
30
- 3. Optional: `GET https://api.xstocks.fi/api/v2/public/assets` returns all assets with the same `deployments` shape.
32
+ 3. Optional: `curl -s "https://api.xstocks.fi/api/v2/public/assets"` returns all assets with the same `deployments` shape.
31
33
 
32
- 4. Call `get_jetton_info` with that address to confirm **name / symbol / decimals** before swapping.
34
+ 4. Call `get_jetton_info` with `--jettonAddress <jetton_master>` to confirm **name / symbol / decimals** before swapping.
33
35
 
34
36
  ## MCP tools
35
37
 
@@ -42,6 +44,20 @@ Backed **xStocks** are jettons on TON. Resolve the **jetton master** from the pu
42
44
 
43
45
  Amounts for `get_swap_quote` are **human-readable** strings (respect jetton decimals from `get_jetton_info`).
44
46
 
47
+ ## CLI argument names (exact)
48
+
49
+ | Tool | Arg | CLI flag |
50
+ | ---- | --- | -------- |
51
+ | `get_jetton_info` | jettonAddress | `--jettonAddress` |
52
+ | `get_jetton_balance` | jettonAddress | `--jettonAddress` |
53
+ | `get_swap_quote` | fromToken | `--fromToken` (use `"TON"` for native TON, jetton master address for tokens) |
54
+ | `get_swap_quote` | toToken | `--toToken` |
55
+ | `get_swap_quote` | amount | `--amount` (human-readable) |
56
+ | `get_swap_quote` | slippageBps | `--slippageBps` (default 100 = 1%) |
57
+ | `emulate_transaction` | messages | `--messages` (JSON array from quote's `transaction.messages`) |
58
+ | `send_raw_transaction` | messages | `--messages` (same JSON array) |
59
+ | `get_transaction_status` | normalizedHash | `--normalizedHash` |
60
+
45
61
  ## Pre-fund USDT (auto, when needed)
46
62
 
47
63
  Before any xStock trade, check the user's USDT balance:
@@ -49,7 +65,7 @@ Before any xStock trade, check the user's USDT balance:
49
65
  1. `get_jetton_balance` for the USDT master address — use the `amount` field for comparison.
50
66
  2. If `amount` **< required amount** for the planned buy:
51
67
  a. Calculate the shortfall (include a small buffer for price movement).
52
- b. `get_swap_quote` with `fromToken` = native TON, `toToken` = USDT master, `amount` = shortfall.
68
+ b. `get_swap_quote` with `fromToken` = `"TON"` (the literal string, not an address), `toToken` = USDT master, `amount` = shortfall.
53
69
  c. Confirm with the user: *"You need ~X USDT but only have Y. Swap Z TON → X USDT first?"*
54
70
  d. On approval, `send_raw_transaction` → poll `get_transaction_status` until `completed`.
55
71
  e. Re-check USDT balance before proceeding to the xStock buy.
@@ -62,7 +78,7 @@ Before any xStock trade, check the user's USDT balance:
62
78
  4. `emulate_transaction` with the quote's `transaction.messages` — verify expected balance changes before sending.
63
79
  5. Show the user: **fromAmount**, **toAmount**, **minReceived**, **expiresAt**, emulation results, and note the forward **TON** on router messages (gas).
64
80
  6. Confirm once, then `send_raw_transaction` with the returned `transaction.messages`.
65
- 6. Poll `get_transaction_status` on `normalizedHash` until `completed` or `failed`.
81
+ 7. Poll `get_transaction_status` on `normalizedHash` until `completed` or `failed`.
66
82
 
67
83
  > **Do not attempt TON → xStock directly.** It will return no quote. Always route through USDT.
68
84