gate-dex-mcpswap

Gate Wallet Swap/DEX trading. Get quotes, execute Swap. Use when user wants to 'swap USDT for ETH', 'swap', 'exchange tokens', 'buy tokens', 'sell tokens'. Includes mandatory three-step confirmation gate. Supports EVM multi-chain + Solana, supports cross-chain Swap.

$ npx skills add https://github.com/gate/gate-skills --skill gate-dex-mcpswap

Gate Wallet Swap Skill

Swap/DEX domain — Quote fetching, slippage control, route display, Swap execution (One-shot), status tracking, with mandatory three-step confirmation gate. 3 MCP tools + 2 cross-Skill calls + 1 MCP Resource.

Trigger scenarios: User mentions "swap", "exchange", "convert", "buy", "sell", "convert X to Y", "cross-chain", or when other Skills guide the user to perform token exchange operations.

Step 0: MCP Server Connection Check (Mandatory)

Before executing any operation, Gate Wallet MCP Server availability must be confirmed. This step cannot be skipped.

Probe call:

CallMcpTool(server="gate-wallet", toolName="chain.config", arguments={chain: "ETH"})
ResultHandling
SuccessMCP Server available, proceed to subsequent steps
server not found / unknown serverCursor not configured → Show configuration guide (see below)
connection refused / timeoutRemote unreachable → Prompt to check URL and network
401 / unauthorizedAPI Key authentication failed → Prompt to check auth configuration

Display when Cursor is not configured

❌ Gate Wallet MCP Server not configured

The MCP Server named "gate-wallet" was not found in Cursor. Please configure as follows:

Method 1: Via Cursor Settings (recommended)
  1. Open Cursor → Settings → MCP
  2. Click "Add new MCP server"
  3. Fill in:
     - Name: gate-wallet
     - Type: HTTP
     - URL: https://your-mcp-server-domain/mcp
  4. Save and retry

Method 2: Manual config file edit
  Edit ~/.cursor/mcp.json, add:
  {
    "mcpServers": {
      "gate-wallet": {
        "url": "https://your-mcp-server-domain/mcp"
      }
    }
  }

If you don't have an MCP Server URL yet, please contact the administrator.

Display when remote service is unreachable

⚠️  Gate Wallet MCP Server connection failed

MCP Server config found, but unable to connect to remote service. Please check:
1. Confirm service URL is correct (is the configured URL accessible)
2. Check network connection (VPN / firewall impact)
3. Confirm remote service is running normally

Display when API Key authentication fails

🔑 Gate Wallet MCP Server authentication failed

MCP Server connected but API Key validation failed. The service uses AK/SK authentication (x-api-key header).
Please contact the administrator for a valid API Key and confirm server-side configuration.

Authentication

All operations in this Skill require mcp_token. User must be logged in before calling any tool.

  • If no mcp_token → Guide to gate-dex-mcpauth to complete login, then return.
  • If mcp_token expired (MCP Server returns token expired error) → First try auth.refresh_token silent refresh, on failure guide to re-login.

MCP Resource

swap://supported_chains — List of chains supported for Swap

Before calling tx.quote or tx.swap, this Resource must be read to verify chain_id supports Swap and determine address grouping (EVM vs Solana).

FetchMcpResource(server="gate-wallet", uri="swap://supported_chains")

Returns chain list grouped by address type (evm / solana), used for:

  • Verifying user-specified chain supports Swap
  • Determining whether user_wallet should use EVM address or SOL address
  • Cross-chain Swap: determining if source and target chains belong to different address groups (requires to_wallet)

MCP Tool Call Specification

1. wallet.get_token_list (Cross-Skill call) — Query balance for validation

Must call this tool before Swap to validate input token balance and Gas token balance. This tool belongs to gate-dex-mcpwallet domain, called here cross-Skill.

FieldDescription
Tool namewallet.get_token_list
Parameters{ chain?: string, network_keys?: string, account_id?: string, mcp_token: string, page?: number, page_size?: number }
Return valueToken array, each item contains symbol, balance, price, value, chain, contract_address, etc.

Parameter description:

ParameterRequiredDescription
chainNoSingle-chain query (e.g. "ETH"), backward compatible
network_keysNoMulti-chain query, comma-separated (e.g. "ETH,SOL,ARB")
account_idNoUser account ID, can be auto-detected from login session
mcp_tokenYesAuth token
pageNoPage number, default 1
page_sizeNoPage size, default 20

Call example:

CallMcpTool(
  server="gate-wallet",
  toolName="wallet.get_token_list",
  arguments={ chain: "ETH", mcp_token: "<mcp_token>" }
)

Agent behavior: Extract input token (sell token) balance and chain native token balance (for Gas) from returned list, prepare for subsequent balance validation. Also resolve token symbol to contract address.


2. wallet.get_addresses (Cross-Skill call) — Get chain-specific wallet addresses

Both tx.quote and tx.swap require user_wallet parameter. This tool must be called first to get user wallet addresses on different chain types. This tool belongs to gate-dex-mcpwallet domain, called here cross-Skill.

FieldDescription
Tool namewallet.get_addresses
Parameters{ account_id: string, mcp_token: string }
Return valueAddress mapping, e.g. { "EVM": "0x...", "SOL": "5x..." }

Parameter description:

ParameterRequiredDescription
account_idYesUser account ID
mcp_tokenYesAuth token

Call example:

CallMcpTool(
  server="gate-wallet",
  toolName="wallet.get_addresses",
  arguments={ account_id: "acc_12345", mcp_token: "<mcp_token>" }
)

Return example:

{
  "EVM": "0x1234567890abcdef1234567890abcdef12345678",
  "SOL": "5xAbCdEf1234567890abcdef1234567890abcdef12"
}

Agent behavior:

  • EVM chains (ETH/BSC/Polygon/Arbitrum/Base/Avalanche) → Use addresses["EVM"] as user_wallet
  • Solana (chain_id=501) → Use addresses["SOL"] as user_wallet
  • Cross-chain Swap with source and target different address groups → Source chain address as user_wallet, target chain address as to_wallet

3. tx.quote — Get Swap quote

Get Swap quote from input token to output token, including exchange rate, slippage, route path, estimated Gas, etc. Before calling: ① User must confirm slippage (via AskQuestion or explicitly in message); ② Read swap://supported_chains Resource to verify chain support; ③ Call wallet.get_addresses to get wallet address. Do not call this tool until slippage is confirmed.

FieldDescription
Tool nametx.quote
Parameters{ chain_id_in: number, chain_id_out: number, token_in: string, token_out: string, amount: string, slippage: number, user_wallet: string, native_in: number, native_out: number, mcp_token: string, to_wallet?: string }
Return valueQuote info, including estimated output amount, route path (routes), Gas fee, price impact, etc. routes[].need_approved value 2 means token approval required

Parameter description:

ParameterRequiredDescription
chain_id_inYesSource chain ID (ETH=1, BSC=56, Polygon=137, Arbitrum=42161, Base=8453, Avalanche=43114, Solana=501)
chain_id_outYesTarget chain ID. Same-chain Swap: same as chain_id_in; Cross-chain Swap: target chain ID
token_inYesInput token contract address. Native token use "-". If native_in=1 auto-normalizes to "-"
token_outYesOutput token contract address. Native token use "-". If native_out=1 auto-normalizes to "-"
amountYesInput token amount (human-readable format, e.g. "100", do not convert to wei/lamports)
slippageYesSlippage tolerance, decimal ratio (0.01 = 1%, 0.03 = 3%). Range 0.001~0.499. Default 0.03 (3%)
user_walletYesUser source chain wallet address, from wallet.get_addresses
native_inYes⚠️ Critical field, wrong value causes tx failure or fund loss. Check if token_in is native: Native (ETH, BNB, MATIC, AVAX, SOL) = 1, Contract token (USDT, USDC, WETH, WBNB, etc.) = 0. User saying "BNB" defaults to native; only explicit "WBNB" is contract token. See "native_in / native_out rules" below
native_outYes⚠️ Critical field, wrong value causes tx failure or fund loss. Check if token_out is native: Native (ETH, BNB, MATIC, AVAX, SOL) = 1, Contract token (USDT, USDC, WETH, WBNB, etc.) = 0. User saying "SOL" defaults to native; only explicit "WSOL" is contract token. See "native_in / native_out rules" below
mcp_tokenYesAuth token
to_walletRequired for cross-chainTarget chain receiving address. Only needed when cross-chain and source/target belong to different address groups (e.g. EVM→Solana)

native_in / native_out rules

These fields determine how the backend normalizes token addresses; wrong values cause tx failure. Rules are simple:

Check if token_in / token_out itself is native (Gas token):

  • native_in: token_in is native → 1, is contract token → 0
  • native_out: token_out is native → 1, is contract token → 0

Native vs contract token reference:

Native (native=1)Corresponding Wrapped contract token (native=0)Note
ETHWETHUser saying "ETH" defaults to native; only explicit "WETH" is contract token
BNBWBNBUser saying "BNB" defaults to native; only explicit "WBNB" is contract token
MATICWMATICUser saying "MATIC" defaults to native
AVAXWAVAXUser saying "AVAX" defaults to native
SOLWSOLUser saying "SOL" defaults to native

Common contract tokens (always native=0): USDT, USDC, DAI, CAKE, ARB, OP, RAY, JUP, etc.

Cross-chain examples:

  • USDT(BSC) → SOL(Solana): token_in=USDT is contract token → native_in=0, token_out=SOL is native → native_out=1
  • ETH(Ethereum) → USDT(BSC): token_in=ETH is native → native_in=1, token_out=USDT is contract token → native_out=0
  • USDC(Ethereum) → USDC(Polygon): both contract tokens → native_in=0, native_out=0
  • ETH(Ethereum) → SOL(Solana): both native → native_in=1, native_out=1
  • BNB(BSC) → ETH(Ethereum): both native → native_in=1, native_out=1

Common mistakes:

  • ❌ Treating "BNB" as WBNB (contract token) when user says "BNB"; should be native=1
  • ❌ Treating WETH/WBNB/WSOL etc. as native (they are contract tokens, native=0)
  • ❌ Cross-chain: native_out not passed or default 0, causing backend to misidentify target token

Call example (same-chain Swap: USDT→ETH on ETH):

CallMcpTool(
  server="gate-wallet",
  toolName="tx.quote",
  arguments={
    chain_id_in: 1,
    chain_id_out: 1,
    token_in: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
    token_out: "-",
    amount: "100",
    slippage: 0.03,
    user_wallet: "0x1234567890abcdef1234567890abcdef12345678",
    native_in: 0,
    native_out: 1,
    mcp_token: "<mcp_token>"
  }
)

Call example (cross-chain Swap: ETH→Solana SOL):

CallMcpTool(
  server="gate-wallet",
  toolName="tx.quote",
  arguments={
    chain_id_in: 1,
    chain_id_out: 501,
    token_in: "-",
    token_out: "-",
    amount: "0.1",
    slippage: 0.03,
    user_wallet: "0x1234...5678",
    native_in: 1,
    native_out: 1,
    to_wallet: "5xAbCd...ef12",
    mcp_token: "<mcp_token>"
  }
)

Agent behavior:

  1. Must show quote summary table to user after getting quote (see "Quote display template" below)
  2. Calculate exchange value difference (see formula below), warn user prominently when > 5%
  3. Check need_approved: when value is 2, inform user token approval needed and emphasize
  4. Do not execute Swap directly, must wait for user confirmation

tx.quote return value key field mapping

Field pathTypeDescriptionDisplay use
amount_instringInput token amount (human-readable)Pay amount
amount_outstringEstimated output token amount (human-readable)Receive amount
min_amount_outstringMinimum receive amount (with slippage protection)Min receive
slippagestringActual slippage used (decimal, e.g. "0.010000" = 1%)Slippage info
from_token.token_symbolstringInput token symbolToken name
from_token.token_pricestringInput token unit price (USD)Value diff calculation
from_token.chain_namestringInput token chain nameChain info
from_token.chain_idnumberInput token chain IDChain info
to_token.token_symbolstringOutput token symbolToken name
to_token.token_pricestringOutput token unit price (USD)Value diff calculation
to_token.chain_namestringOutput token chain nameChain info (different for cross-chain)
estimate_gas_fee_amountstringGas fee (native token amount)Gas display
estimate_gas_fee_amount_usdstringGas fee (USD)Gas display
estimate_tx_timestringEstimated tx confirmation time (seconds)Arrival time
need_approvednumberWhether token approval needed (2=needs approval, other=no approval)Approval prompt
is_signal_chainnumber1=same chain, 2=cross-chainCross-chain flag
provider.namestringDEX/aggregator/bridge nameRoute display
provider.feestringService/bridge fee (has value for cross-chain)Fee display
provider.fee_symbolstringFee token symbol (has value for cross-chain)Fee display
handlers[].typestring"swap" = DEX exchange, "bridge" = cross-chain bridgeRoute type
handlers[].routes[].sub_routes[][].namestringSpecific DEX/bridge name (e.g. PANCAKE_V2, Bridgers)Route detail
handlers[].routes[].sub_routes[][].name_instringRoute intermediate input token nameRoute path
handlers[].routes[].sub_routes[][].name_outstringRoute intermediate output token nameRoute path
trading_fee.ratenumberPlatform trading fee rate (e.g. 0.003 = 0.3%, may have value for single-chain)Fee display
trading_fee.enablebooleanWhether trading fee enabledFee display
pool.liquiditystringPool total liquidity (USD, has value for single-chain)Liquidity reference
quote_idstringQuote ID (internal identifier)Log tracking

Exchange value difference calculation

input_value_usd  = float(amount_in) × float(from_token.token_price)
output_value_usd = float(amount_out) × float(to_token.token_price)
price_diff_pct   = (input_value_usd - output_value_usd) / input_value_usd × 100

This value difference includes all costs (DEX fee, bridge fee, slippage loss, price impact, etc.), the total cost ratio actually borne by the user.

Value diff rangeHandling
< 1%Normal, no extra prompt
1% ~ 3%Normal range, can note in quote
3% ~ 5%Prompt "exchange value difference is high"
> 5%Prominent warning: Show value diff details, use AskQuestion for user confirmation (see "Exchange value diff > 5% mandatory warning" template)

4. tx.swap — Execute Swap (One-shot)

One-shot Swap: Quote→Build→Sign→Submit completed in single call. Eliminates multiple round-trip delays (solves Solana blockhash expiry). Internal retry up to 3 times.

Only call after completing three-step confirmation SOP (see operation flow below).

FieldDescription
Tool nametx.swap
Parameters{ chain_id_in: number, chain_id_out: number, token_in: string, token_out: string, amount: string, slippage: number, user_wallet: string, native_in: number, native_out: number, account_id: string, mcp_token: string, to_wallet?: string }

Success return value

FieldTypeDescription
tx_hashstringOn-chain tx hash
tx_order_idstringInternal order ID, for tx.swap_detail polling
amount_instringActual input amount (human-readable)
amount_outstringEstimated output amount (human-readable)
from_tokenstringInput token symbol
to_tokenstringOutput token symbol
slippagenumberSlippage used (decimal)
route_pathstring[]List of DEX names in route
need_approvedbooleanWhether ERC20 approval was executed
statusstringFixed "submitted"
messagestring"Transaction submitted. Poll tx.swap_detail with tx_order_id every 5s."

Failure return value (all 3 retries failed)

FieldTypeDescription
statusstringFixed "failed"
messagestring"Swap failed after 3 attempts"
attemptsarrayDetail array for each attempt, each with attempt (sequence), error (error message)

Parameter description:

ParameterRequiredDescription
chain_id_inYesSource chain ID
chain_id_outYesTarget chain ID. Same-chain Swap same as chain_id_in
token_inYesInput token contract address, native token "-"
token_outYesOutput token contract address, native token "-"
amountYesHuman-readable amount (e.g. "0.01")
slippageYesSlippage, decimal ratio (0.01=1%, 0.03=3%)
user_walletYesSource chain wallet address
native_inYes⚠️ Critical field, same rules as tx.quote. Check if token_in is native: Native (ETH/BNB/MATIC/AVAX/SOL) = 1, contract token = 0. User saying "BNB" defaults to native. See "native_in / native_out rules" in tx.quote above
native_outYes⚠️ Critical field, same rules as tx.quote. Check if token_out is native: Native (ETH/BNB/MATIC/AVAX/SOL) = 1, contract token = 0. User saying "SOL" defaults to native. See "native_in / native_out rules" in tx.quote above
account_idYesUser account ID (UUID)
mcp_tokenYesAuth token
to_walletRequired for cross-chainTarget chain receiving address (needed when crossing different address groups)

Call example:

CallMcpTool(
  server="gate-wallet",
  toolName="tx.swap",
  arguments={
    chain_id_in: 1,
    chain_id_out: 1,
    token_in: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
    token_out: "-",
    amount: "100",
    slippage: 0.03,
    user_wallet: "0x1234567890abcdef1234567890abcdef12345678",
    native_in: 0,
    native_out: 1,
    account_id: "acc_12345",
    mcp_token: "<mcp_token>"
  }
)

Return example (success):

FieldExample value
tx_hash0xa1b2c3d4e5f6...7890
tx_order_idorder_abc123
amount_in100
amount_out0.052
from_tokenUSDT
to_tokenETH
slippage0.03
route_path["PANCAKE_V2"]
need_approvedfalse
statussubmitted
messageTransaction submitted. Poll tx.swap_detail with tx_order_id every 5s.

Return example (failure):

FieldExample value
statusfailed
messageSwap failed after 3 attempts
attempts[0].errorinsufficient balance
attempts[1].errorquote failed: liquidity too low
attempts[2].errorquote failed: liquidity too low

Agent behavior:

  • Success (status == "submitted") → Show user tx_hash, from_token/to_token, amount_in/amount_out, with block explorer link, then poll tx.swap_detail with tx_order_id
  • Failure (status == "failed") → Show message and each attempts[].error, no auto retry, suggest user re-fetch quote

5. tx.swap_detail — Query Swap status

Query execution result and details of submitted Swap transaction. Use tx_order_id returned by tx.swap.

FieldDescription
Tool nametx.swap_detail
Parameters{ tx_order_id: string, mcp_token: string }
Return valueSwap transaction details, including status, token info, timestamp, Gas fee, etc.

Parameter description:

ParameterRequiredDescription
tx_order_idYestx_order_id returned by tx.swap
mcp_tokenYesAuth token

Return value key fields:

FieldTypeDescription
statusnumberTx status: 0=success, 3=failed
tokenInSymbolstringInput token symbol
tokenOutSymbolstringOutput token symbol
amountInstringInput amount (min unit)
amountOutstringOutput amount (min unit)
tokenInDecimalsnumberInput token decimals
tokenOutDecimalsnumberOutput token decimals
srcHashstringOn-chain tx hash
srcHashExplorerUrlstringBlock explorer URL prefix
unifyGasFeestringActual Gas fee (min unit)
unifyGasFeeDecimalnumberGas token decimals
unifyGasFeeSymbolstringGas token symbol
gasFeeUsdstringActual Gas fee (USD)
creationTimestringTx creation time (ISO8601)
errorCodenumberError code (0=no error)
errorMsgstringError message (has value on failure)

Gas fee human-readable conversion: float(unifyGasFee) / 10^unifyGasFeeDecimal, unit is unifyGasFeeSymbol.

Call example:

CallMcpTool(
  server="gate-wallet",
  toolName="tx.swap_detail",
  arguments={
    tx_order_id: "order_abc123",
    mcp_token: "<mcp_token>"
  }
)

Return value status meaning:

statusMeaningNext action
pendingTx pending confirmationPoll every 5 seconds, max 3 minutes; on timeout guide user to view via tx.history_list
successSwap completed successfullyShow final result to user
failedSwap failedShow failure reason, suggest re-fetch quote

Supported chains

chain_idNetwork nameTypeNative Gas tokenBlock explorerchain.config identifier
1EthereumEVMETHetherscan.ioETH
56BNB Smart ChainEVMBNBbscscan.comBSC
137PolygonEVMMATICpolygonscan.comPOLYGON
42161Arbitrum OneEVMETHarbiscan.ioARB
10OptimismEVMETHoptimistic.etherscan.ioOP
43114Avalanche C-ChainEVMAVAXsnowtrace.ioAVAX
8453BaseEVMETHbasescan.orgBASE
501SolanaNon-EVMSOLsolscan.ioSOL

Common chain_id can be used directly; only call chain.config for uncommon chains.

Before calling tx.quote / tx.swap, always read swap://supported_chains Resource to confirm chain supports Swap.

Token address resolution

Agent needs to convert user-provided token name/symbol to contract address and native flag when collecting Swap parameters:

User inputResolutiontoken_in/token_outnative_in/native_out
Native token (ETH, BNB, SOL, MATIC, AVAX)Mark as native"-"1
Token symbol (e.g. USDT, USDC)Match symbol from wallet.get_token_list holdings to get contract_addressContract address0
Contract address (e.g. 0xdAC17...)Use directlyPass as-is0

⚠️ Native flag rule: Check if token itself is native

  • native_in: token_in is native (ETH/BNB/SOL/MATIC/AVAX) → 1, contract token → 0
  • native_out: token_out is native → 1, contract token → 0
  • User saying "BNB" defaults to native (native=1); only explicit "WBNB" is contract token (native=0). Same for ETH vs WETH, SOL vs WSOL
  • WETH, WBNB, WSOL etc. are contract tokens (native=0), not native

When user-provided token symbol not found in holdings:

  • Prompt user to confirm token name is correct
  • Prompt user to provide contract address
  • Suggest using gate-dex-mcpmarket (token_get_coin_info) to query token info for contract address

MCP tool call chain overview

Complete Swap flow calls the following tools in sequence, forming a strict linear pipeline:

0.  chain.config                                      ← Step 0: MCP Server pre-check
1.  FetchMcpResource(swap://supported_chains)         ← Verify chain supports Swap + address grouping
2.  wallet.get_token_list                             ← Cross-Skill: query balance (input token + Gas token) + resolve token address
3.  wallet.get_addresses                              ← Cross-Skill: get chain-specific wallet address (user_wallet / to_wallet)
4.  [Agent balance validation: input token balance >= amount]            ← Agent internal logic, not MCP call
5.  [Agent show trade pair confirmation Table, wait for user confirm]         ← tx.swap SOP Step 1 (mandatory gate)
6.  tx.quote                                          ← Get quote (estimated output, route, Gas, price impact)
7.  [Agent show quote details + check need_approved]          ← tx.swap SOP Step 2 (mandatory gate)
8.  [Agent sign approval confirm, wait for user confirm]                  ← tx.swap SOP Step 3 (mandatory gate)
9.  tx.swap                                           ← One-shot execution (Quote→Build→Sign→Submit)
10. tx.swap_detail (by tx_order_id, poll every 5s)       ← Query Swap result (optional, poll as needed)

Skill routing

Route to corresponding Skill based on user intent after Swap:

User intentRoute target
View updated balancegate-dex-mcpwallet
View Swap tx historygate-dex-mcpwallet (tx.history_list)
Continue Swap other tokensStay in this Skill
Transfer just-swapped tokensgate-dex-mcptransfer
View token market / K-linegate-dex-mcpmarket
Login / auth expiredgate-dex-mcpauth

Operation flow

Flow A: Standard Swap (main flow)

Step 0: MCP Server pre-check
  Call chain.config({chain: "ETH"}) to probe availability
  ↓ Success

Step 1: Auth check
  Confirm valid mcp_token and account_id
  No token → Guide to gate-dex-mcpauth login
  ↓

Step 2: Intent recognition + parameter collection
  Extract Swap intent from user input, collect required parameters:
  - from_token: Input token (required, e.g. USDT)
  - to_token: Output token (required, e.g. ETH)
  - amount: Input amount (required, e.g. 100)
  - chain: Target chain (optional, infer from token or context, default Ethereum chain_id=1)
  - slippage: Slippage tolerance (optional, see interactive selection below)

  When from_token / to_token / amount missing, ask user item by item.

  **Slippage selection**: If user already specified slippage in message, use directly, no need to ask.
  If not specified, use AskQuestion for user to select:

AskQuestion({ title: "Slippage setting", questions: [{ id: "slippage", prompt: "Please select slippage tolerance (affects minimum receive amount)", options: [ { id: "0.005", label: "0.5% (recommended for stablecoins)" }, { id: "0.01", label: "1% (recommended for major tokens)" }, { id: "0.03", label: "3% (default, recommended for volatile tokens)" }, { id: "0.05", label: "5% (low liquidity tokens)" }, { id: "custom", label: "Custom" } ] }] })


User selects "Custom" → Ask for specific value (input percentage, Agent converts to decimal ratio)
↓ Parameters complete

Step 3: Verify chain support
Read swap://supported_chains Resource
Confirm user-specified chain chain_id in support list
Determine address grouping (EVM / Solana)
↓

Step 4: Query balance (Cross-Skill: gate-dex-mcpwallet)
Call wallet.get_token_list({ chain: "ETH", mcp_token })
Extract:
- Input token balance (e.g. USDT balance)
- Chain native Gas token balance (e.g. ETH balance)
Also resolve user-provided token symbol to contract address (token_in, token_out) and native flag
↓

Step 5: Get wallet address (Cross-Skill: gate-dex-mcpwallet)
Call wallet.get_addresses({ account_id, mcp_token })
Get user_wallet by source chain type:
- EVM chain → addresses["EVM"]
- Solana → addresses["SOL"]
Cross-chain Swap with different address groups → Also get to_wallet
↓

Step 6: Agent balance validation (mandatory)
Validation rules:
a) Input token is native: balance >= amount + estimated_gas (Gas precisely validated after quote)
b) Input token is ERC20/SPL: token_balance >= amount and native_balance > 0 (ensure Gas available)

Validation failed → Abort Swap, show insufficient info:

────────────────────────────
❌ Insufficient balance, cannot execute Swap

Input token: USDT
Swap amount: 100 USDT
Current USDT balance: 80 USDT (insufficient, short 20 USDT)

Suggestions:
- Reduce Swap amount
- Deposit tokens to wallet first
────────────────────────────

↓ Validation passed

Step 7: SOP Step 1 — Confirm trade pair (mandatory gate)
Show trade pair confirmation Table to user, use AskQuestion for confirmation:

| Field | Value |
|-------|------|
| from_token | {symbol}({contract_address}) |
| to_token | {symbol}({contract_address}) |
| amount | {amount} |
| chain | {chain_name} (chain_id={chain_id}) |
| slippage | {slippage}% (user selected) |

AskQuestion({
  title: "Trade pair confirmation",
  questions: [{
    id: "trade_confirm",
    prompt: "Please confirm the above trade information is correct",
    options: [
      { id: "confirm", label: "Confirm, continue to get quote" },
      { id: "modify_slippage", label: "Modify slippage" },
      { id: "modify_amount", label: "Modify amount" },
      { id: "cancel", label: "Cancel trade" }
    ]
  }]
})

User selects confirm → Continue
User selects modify_slippage → Re-show AskQuestion slippage selection
User selects modify_amount → Ask for new amount then re-show Table
User selects cancel → Abort Swap
(Fallback to text reply when AskQuestion unavailable)
↓ User confirmed

Step 8: SOP Step 2 — Get quote and display (mandatory gate, cannot skip)
Call tx.quote({
  chain_id_in, chain_id_out, token_in, token_out, amount, slippage,
  user_wallet, native_in, native_out, mcp_token, to_wallet?
})

Must show user:
- Estimated to_token receive amount
- Route/DEX path
- Estimated Gas fee
- Price impact (warn when > 5%)
- Approval requirement (when need_approved == 2, inform token approval needed)
↓

Step 9: Quote risk assessment (Agent internal logic)
Check risk indicators in quote:
a) Exchange value difference (price_diff_pct):
   input_value_usd  = float(amount_in) × float(from_token.token_price)
   output_value_usd = float(amount_out) × float(to_token.token_price)
   price_diff_pct   = (input_value_usd - output_value_usd) / input_value_usd × 100
   - < 1%: Normal
   - 1% ~ 3%: Normal range
   - 3% ~ 5%: Prompt "exchange value difference is high"
   - > 5%: **Prominent warning** — Show input_value_usd, output_value_usd, difference, use AskQuestion for user to confirm (see "Exchange value diff > 5% mandatory warning" template)
b) Slippage:
   - User setting > 5% (i.e. > 0.05): Warn "slippage set high, actual execution price may deviate significantly"
c) Gas fee:
   - Gas fee as % of Swap amount > 10%: Prompt "Gas fee ratio high, suggest larger Swap amount or wait for network idle"
d) Native token Gas balance precise validation:
   - native_balance < estimated_gas → Abort, prompt Gas insufficient
↓

Step 10: SOP Step 3 — Sign approval confirmation (mandatory gate)
Inform user:
"The next step involves contract approval or transaction signing. This is necessary to execute the trade.
 After confirmation, the system will automatically complete Quote→Build→Sign→Submit full flow."

Use AskQuestion for final confirmation:

AskQuestion({
  title: "Sign approval confirmation",
  questions: [{
    id: "sign_confirm",
    prompt: "Confirm execute trade? System will automatically complete signing and submission",
    options: [
      { id: "confirm", label: "Confirm execute" },
      { id: "modify", label: "Modify slippage/amount" },
      { id: "cancel", label: "Cancel trade" }
    ]
  }]
})

(Fallback to text reply when AskQuestion unavailable)
↓

User selects confirm → Continue Step 11
User selects cancel → Abort Swap, show cancel prompt
User selects modify → Return to Step 7 re-show trade pair Table and re-fetch quote

Step 11: Execute Swap (One-shot)
Call tx.swap({
  chain_id_in, chain_id_out, token_in, token_out, amount, slippage,
  user_wallet, native_in, native_out, account_id, mcp_token, to_wallet?
})
Get tx_hash and tx_order_id
↓

Step 12: Query Swap result (as needed)
Call tx.swap_detail({ tx_order_id, mcp_token })
Poll every 5 seconds, max 3 minutes (~36 times), until terminal state:
- status == "pending" → Inform user tx pending, continue polling
- status == "success" → Show final execution result
- status == "failed" → Show failure info
- Still "pending" after 3 minutes → Stop polling, inform user:
  "Transaction still processing, please check result later via transaction list."
  Guide user to call tx.history_list({ account_id, mcp_token }) to view Swap tx history
↓

Step 13: Show result + follow-up suggestions

────────────────────────────
✅ Swap executed successfully!

Input: 100 USDT
Received: 0.0521 ETH
Gas fee: 0.00069778 ETH (≈ $1.46)
Tx Hash: {tx_hash}
Block explorer: https://{explorer}/tx/{tx_hash}

You can:
- View updated balance
- View Swap history
- Continue other operations
────────────────────────────

Flow B: Re-quote after modifying slippage

Trigger: User requests slippage change at confirmation step
  ↓
Step 1: Record new slippage value
  User specifies new slippage (e.g. "change slippage to 1%")
  Convert to decimal ratio (1% → 0.01)
  ↓
Step 2: Re-fetch quote
  Re-call tx.quote with new slippage (other params unchanged)
  ↓
Step 3: Re-display quote details
  Show updated quote info (new min output amount will change)
  ↓
  Wait for user to confirm again or continue modifying
  After confirm, proceed to sign approval confirmation (SOP Step 3)

Flow C: Query Swap transaction status

Step 0: MCP Server pre-check
  ↓ Success

Step 1: Auth check
  ↓

Step 2: Query Swap status
  Call tx.swap_detail({ tx_order_id, mcp_token })
  ↓

Step 3: Display status

  ── Swap Status ──────────────
  Order ID: {tx_order_id}
  Status: {status} (success / pending / failed)
  Input: {from_amount} {from_token}
  Output: {to_amount} {to_token}
  Gas fee: {gas_fee} {gas_symbol} (≈ ${gas_fee_usd})
  Tx Hash: {tx_hash}
  Block explorer: https://{explorer}/tx/{tx_hash}
  ────────────────────────────

Flow D: Cross-chain Swap

Trigger: User wants to exchange A-chain asset to B-chain (e.g. USDT on ETH → SOL on Solana)
  ↓
Step 1: Verify cross-chain support
  Read swap://supported_chains Resource
  Confirm chain_id_in and chain_id_out both in support list
  Determine address grouping: whether source and target chains belong to different address groups
  ↓

Step 2: Get wallet addresses
  Call wallet.get_addresses({ account_id, mcp_token })
  - user_wallet = Source chain address (e.g. EVM address)
  - to_wallet = Target chain address (e.g. SOL address, only when crossing different address groups)
  ↓

Step 3: Same as Flow A from Step 6 onward
  Set chain_id_in != chain_id_out in tx.quote and tx.swap
  And pass to_wallet parameter

Swap confirmation templates

Three-step confirmation SOP must be completed before tx.swap execution; each step is a mandatory gate that cannot be skipped.

Interaction strategy

For all gate steps requiring user confirmation/cancel input, prefer AskQuestion tool for structured options to improve interaction efficiency:

  • When AskQuestion available: Let user quickly select via option buttons (confirm, cancel, modify params, etc.)
  • When AskQuestion unavailable (tool call failed or platform unsupported): Fallback to text reply mode, prompt user to reply "confirm"/"cancel"

SOP Step 1: Trade pair confirmation Table

After showing the Table below, use AskQuestion for user to confirm or modify:

| Field | Value |
|-------|------|
| from_token | {from_symbol}({from_contract_address}) |
| to_token | {to_symbol}({to_contract_address}) |
| amount | {amount} |
| chain | {chain_name} (chain_id={chain_id_in}) |
| slippage | {slippage}% (user selected) |

Interaction (prefer AskQuestion):

AskQuestion({
  title: "Trade pair confirmation",
  questions: [{
    id: "trade_confirm",
    prompt: "Please confirm the above trade information is correct",
    options: [
      { id: "confirm", label: "Confirm, continue to get quote" },
      { id: "modify_slippage", label: "Modify slippage" },
      { id: "modify_amount", label: "Modify amount" },
      { id: "cancel", label: "Cancel trade" }
    ]
  }]
})
User selectionHandling
confirmContinue SOP Step 2 (get quote)
modify_slippageShow slippage selection AskQuestion, update then re-show Table
modify_amountAsk for new amount, update then re-show Table
cancelAbort Swap, show cancel prompt

Fallback mode: If AskQuestion unavailable, prompt user to reply "confirm" to continue, "cancel" to abort, or specify parameter to modify.

SOP Step 2: Quote details display

After calling tx.quote, must display quote summary in table form. Same template for same-chain/cross-chain, auto-adapt display items based on returned data.

General quote template

Quote Summary

| Item | Content |
|------|---------|
| Chain | {chain info} |
| Pay | {amount_in} {from_token.token_symbol} |
| Receive | ≈ {amount_out} {to_token.token_symbol} |
| Min receive | ≈ {min_amount_out} {to_token.token_symbol} (with {slippage×100}% slippage protection) |
| Rate | 1 {from_token.token_symbol} ≈ {amount_out/amount_in} {to_token.token_symbol} |
| Exchange value diff | ≈ {price_diff_pct}% |
| Route | {route info} |
| Fee | {fee info} |
| Est. Gas | {estimate_gas_fee_amount} {gas_symbol} (≈ ${estimate_gas_fee_amount_usd}) |
| Est. time | ≈ {estimate_tx_time} sec |
| Liquidity | ${pool.liquidity} |
| Approval | {need_approved note} |

Field value rules

Display itemValue logic
ChainSame-chain (is_signal_chain == 1) → from_token.chain_name; Cross-chain (is_signal_chain == 2) → from_token.chain_name → to_token.chain_name
Ratefloat(amount_out) / float(amount_in), add chain name after token symbol for cross-chain
Exchange value diff(input_value_usd - output_value_usd) / input_value_usd × 100 (see calculation above)
Routeprovider.name + handlers[].routes[].sub_routes[][].name; Mark "cross-chain bridge" for cross-chain
Feetrading_fee.enable == truetrading_fee.rate × 100% (trading fee); provider.fee has value → provider.fee provider.fee_symbol (bridge/service fee); omit if both empty
Gas tokenSource chain native token (BSC=BNB, ETH=ETH, Solana=SOL, etc.)
LiquidityShow when pool.liquidity has value, omit row when empty
Approvalneed_approved == 2 → "⚠️ Need to approve {from_symbol} contract first (Token Approval), system will handle automatically"; Other → "No approval needed ✅"
Cross-chain noteWhen is_signal_chain == 2 append below table: "Cross-chain trade involves bridging, actual arrival time may extend due to network congestion."

Example 1: Same-chain Swap (BNB → DOGE on BSC)

Quote Summary

| Item | Content |
|------|---------|
| Chain | BNB Smart Chain |
| Pay | 0.001 BNB |
| Receive | ≈ 4.634 DOGE |
| Min receive | ≈ 4.588 DOGE (with 1% slippage protection) |
| Rate | 1 BNB ≈ 4634 DOGE |
| Exchange value diff | ≈ 0.67% |
| Route | PancakeSwap V2 (PANCAKE_V2) |
| Fee | 0.3% (trading fee) |
| Est. Gas | 0.0000063 BNB (≈ $0.0041) |
| Est. time | ≈ 49 sec |
| Liquidity | $878,530 |
| Approval | Need to approve BNB contract |

Example 2: Cross-chain Swap (Solana USDT → Ethereum USDT)

Quote Summary

| Item | Content |
|------|---------|
| Chain | Solana → Ethereum |
| Pay | 1.707168 USDT |
| Receive | ≈ 1.652046 USDT |
| Min receive | ≈ 1.569443 USDT (with 5% slippage protection) |
| Rate | 1 USDT (Solana) ≈ 0.9677 USDT (ETH) |
| Exchange value diff | ≈ 3.27% |
| Route | MetaPath (via Bridgers cross-chain bridge) |
| Fee | 0.005122 USDT (bridge/service fee) |
| Est. Gas | 0.00000687 SOL (≈ $0.022) |
| Est. time | ≈ 10 sec |
| Approval | No approval needed ✅ |

Note: Exchange value diff is 3.27%, i.e. paying ≈ $1.71 value in tokens,
receiving ≈ $1.65 value in tokens, difference mainly from cross-chain bridge fee and slippage.
Cross-chain trade actual arrival time may extend due to network congestion.

Exchange value diff > 5% mandatory warning

When exchange value diff exceeds 5%, must append prominent warning below quote table and confirm via AskQuestion:

⚠️ Important warning: Exchange value diff is {price_diff_pct}%!
Paying ≈ ${input_value_usd} value in tokens, only receiving ≈ ${output_value_usd} value in tokens.
Difference ≈ ${diff_usd}, mainly from DEX fee, bridge fee, slippage loss and other combined costs.
Strongly suggest: Reduce trade amount, execute in batches, or wait for better quote.

Interaction (prefer AskQuestion):

AskQuestion({
  title: "⚠️ High value diff warning",
  questions: [{
    id: "price_diff_confirm",
    prompt: "Exchange value diff is {price_diff_pct}%, confirm accept this exchange rate?",
    options: [
      { id: "confirm", label: "I understand the risk, continue" },
      { id: "reduce", label: "Reduce trade amount" },
      { id: "cancel", label: "Cancel trade" }
    ]
  }]
})
User selectionHandling
confirmContinue to SOP Step 3 sign confirmation
reduceAsk for new amount, return to SOP Step 1 re-run flow
cancelAbort Swap

Fallback mode: If AskQuestion unavailable, prompt user to reply "confirm" to continue, "cancel" to abort.

SOP Step 3: Sign approval confirmation

After showing prompt text, use AskQuestion for final confirmation:

The next step involves contract approval and transaction signing. This is necessary to execute the trade.
After confirmation, the system will automatically complete Quote→Build→Sign→Submit full flow.

Interaction (prefer AskQuestion):

AskQuestion({
  title: "Sign approval confirmation",
  questions: [{
    id: "sign_confirm",
    prompt: "Confirm execute trade? System will automatically complete signing and submission",
    options: [
      { id: "confirm", label: "Confirm execute" },
      { id: "modify", label: "Modify slippage/amount" },
      { id: "cancel", label: "Cancel trade" }
    ]
  }]
})
User selectionHandling
confirmExecute tx.swap
modifyReturn to SOP Step 1 re-show trade pair Table and re-fetch quote
cancelAbort Swap, show cancel prompt

Fallback mode: If AskQuestion unavailable, prompt user to reply "confirm" to execute, "cancel" to abort, or specify parameter to modify.

High slippage warning (slippage > 5%, i.e. > 0.05)

Append additionally in SOP Step 1 Table and Step 2 quote display:

⚠️ Warning: Current slippage is set to {slippage×100}%, much higher than normal (3%).
This means actual execution price may deviate significantly from quote. Unless you confirm high slippage is needed (e.g. low liquidity token), suggest lowering slippage.
⚠️ High slippage trades may be vulnerable to MEV/sandwich attacks.

Cross-Skill workflow

Complete Swap flow (from login to completion)

gate-dex-mcpauth (login, get mcp_token + account_id)
  → gate-dex-mcpwallet (wallet.get_token_list → validate balance + resolve token address)
  → gate-dex-mcpwallet (wallet.get_addresses → get chain-specific wallet address)
    → gate-dex-mcpswap (trade pair confirm → tx.quote → quote display → sign approval confirm → tx.swap → tx.swap_detail)
      → gate-dex-mcpwallet (view updated balance)

Query and buy workflow

gate-dex-mcpmarket (token_get_coin_info → query token info/market)
  → gate-dex-mcpmarket (token_get_risk_info → security review)
    → gate-dex-mcpwallet (wallet.get_token_list → validate balance)
      → gate-dex-mcpswap (quote → confirm → execute)

Post security review trade workflow

gate-dex-mcpmarket (token_get_risk_info → token security audit)
  → gate-dex-mcpmarket (token_get_coin_info → token details)
    → gate-dex-mcpswap (execute Swap if safe)

Guided by other Skills

Source SkillScenarioDescription
gate-dex-mcpwalletUser wants to exchange after viewing balanceCarries account_id, chain and holdings info
gate-dex-mcpmarketUser wants to buy token after viewing marketCarries token info and chain context
gate-dex-mcptransferUser wants to exchange remaining tokens after transferCarries chain and token context

Calling other Skills

Target SkillCall scenarioTools used
gate-dex-mcpwalletQuery balance and resolve token address before Swapwallet.get_token_list
gate-dex-mcpwalletGet chain-specific wallet address before Swapwallet.get_addresses
gate-dex-mcpwalletView updated balance after Swapwallet.get_token_list
gate-dex-mcpauthNot logged in or token expiredauth.refresh_token or full login flow
gate-dex-mcpmarketQuery token info to help resolve addresstoken_get_coin_info
gate-dex-mcpmarketSecurity review target token before Swaptoken_get_risk_info
gate-dex-mcpwalletView Swap historytx.history_list

Slippage

Slippage is a key parameter in Swap trades, controlling maximum allowed deviation between actual execution price and quote. Use decimal ratio when passing to tx.quote / tx.swap (e.g. 0.03 for 3%), convert to percentage when displaying to user.

Slippage rangeDecimal ratioUse caseNote
0.5% ~ 1%0.005 ~ 0.01Stablecoin pairs (USDT/USDC etc.)Sufficient liquidity, low slippage sufficient
1% ~ 3%0.01 ~ 0.03Volatile tokensDefault recommended range
3% ~ 5%0.03 ~ 0.05Low liquidity / meme tokensNeed to warn user about price deviation
> 5%> 0.05Very low liquidity / high volatilityNeed to warn user, may be vulnerable to MEV/sandwich attacks

Default slippage: 0.03 (3%). If user already specified slippage in message, use directly, no need to ask. Only ask when not provided.

Edge cases and error handling

ScenarioHandling
MCP Server not configuredAbort all operations, show Cursor config guide
MCP Server unreachableAbort all operations, show network check prompt
Not logged in (no mcp_token)Guide to gate-dex-mcpauth to complete login, auto-return to continue Swap
mcp_token expiredFirst try auth.refresh_token silent refresh, on failure guide to re-login
Chain doesn't support SwapAfter reading swap://supported_chains found unsupported → Show supported chain list, ask user to re-select
Input token balance insufficientAbort Swap, show current balance vs required amount difference, suggest reduce amount or deposit first
Gas token balance insufficientAbort Swap, show Gas token insufficient info, suggest get Gas token first
Token symbol cannot resolve to contract addressPrompt user to confirm token name or provide contract address, suggest use gate-dex-mcpmarket to query
tx.quote failedShow error (possible causes: token pair doesn't exist, insufficient liquidity, network congestion). Suggest try different pair or retry later
Exchange value diff > 5%Prominently warn user, show USD value comparison and difference, suggest reduce amount or batch execute. Can still continue if user insists
Slippage > 5% (i.e. > 0.05)Warn user about high slippage risk and MEV attack risk, suggest lower. Can still continue if user insists
Gas fee as % of Swap amount > 10%Prompt user Gas cost is high, suggest larger Swap amount or wait for network idle
tx.swap failedShow failure reason (e.g. balance changed, slippage exceeded, network issue). No auto retry, suggest re-fetch quote
tx.swap_detail returns failed after SwapShow failure reason, suggest re-fetch quote and execute Swap. Token balance may be unchanged
tx.swap_detail stays pending after SwapPoll max 3 minutes; stop on timeout, inform user tx still processing, guide to view via tx.history_list
Input and output token sameReject, prompt input and output token cannot be same
Input amount 0 or negativeReject, prompt enter valid positive amount
Token pair not found on target chainPrompt chain doesn't support this token pair Swap, suggest try on other chain
User cancels confirmation (any step of three-step SOP)Abort immediately, do not execute Swap. Show cancel prompt, stay friendly
Cross-chain Swap different address groups but missing to_walletAuto get target chain address from wallet.get_addresses as to_wallet
EVM address used for Solana (or vice versa)Auto select correct address based on chain_id and swap://supported_chains address grouping
Network interruptionShow network error, suggest check network and retry

Security rules

  1. mcp_token confidentiality: Never display mcp_token in plain text to user; use placeholder <mcp_token> in call examples only.
  2. account_id masking: When displaying to user, only show partial characters (e.g. acc_12...89).
  3. Token auto refresh: When mcp_token expired, prefer silent refresh first, only require re-login on failure.
  4. Balance validation mandatory: Must validate input token balance and Gas token balance before Swap; prohibit Swap execution when balance insufficient.
  5. Three-step confirmation SOP mandatory: Must complete three-step confirmation (trade pair confirm → quote display → sign approval confirm) before executing tx.swap; cannot skip, simplify or auto-confirm any step.
  6. Exchange value diff and slippage risk prompts: Must prominently warn user when exchange value diff > 5% (show USD value comparison); Must warn about high slippage risk and MEV attack risk when slippage > 5% (0.05).
  7. No auto retry on failed trades: After tx.swap execution fails, clearly show error to user, no background auto retry. Suggest re-fetch quote.
  8. Prohibit operations when MCP Server not configured or unreachable: Abort all subsequent steps if Step 0 connection check fails.
  9. MCP Server error transparency: All MCP Server returned errors shown to user as-is, no hiding or tampering.
  10. MEV risk awareness: Trades may be vulnerable to MEV/sandwich attacks with high slippage. Remind this risk when user sets high slippage.
  11. No unlimited approval recommendation: If Swap flow involves token Approve (routes[].need_approved is 2), suggest user use exact approval amount instead of unlimited.
  12. Strict chain address type matching: EVM chains must use EVM address (addresses["EVM"]), Solana must use SOL address (addresses["SOL"]), never mix.

© 2026 Gate Skills Hub. All skills are reviewed before listing.