GDEX MCP Server (gdex-skill)

Servidor MCP para GDEX Pro: trading al contado en 11 redes, perpetuos de Hyperliquid hasta 50x, y copy trading. El apalancamiento y el copy trading conllevan riesgo de pérdida.

Documentación

  ██████╗ ██████╗ ███████╗██╗  ██╗   ██████╗ ██████╗  ██████╗
 ██╔════╝ ██╔══██╗██╔════╝╚██╗██╔╝   ██╔══██╗██╔══██╗██╔═══██╗
 ██║  ███╗██║  ██║█████╗   ╚███╔╝    ██████╔╝██████╔╝██║   ██║
 ██║   ██║██║  ██║██╔══╝   ██╔██╗    ██╔═══╝ ██╔══██╗██║   ██║
 ╚██████╔╝██████╔╝███████╗██╔╝ ██╗   ██║     ██║  ██║╚██████╔╝
  ╚═════╝ ╚═════╝ ╚══════╝╚═╝  ╚═╝   ╚═╝     ╚═╝  ╚═╝ ╚═════╝
               · p r o ·    powered by GEMACH

Habilidad de Agente IA para GDEX Pro — el terminal de trading con autocustodia de Gemach
Spot entre cadenas · Perpetuos HyperLiquid · Copy trading · Portafolio · Descubrimiento de tokens · Custodia gestionada

npm version TypeScript License: MIT skills.sh Tests


Por qué los agentes usan GDEX

GDEX es la superficie de trading. Esta habilidad es cómo los agentes de IA (Claude, Cursor, Codex y más de 40 otros) lo instalan y operan en él — spot, perpetuos, copy-trade y puentes — sin construir su propia infraestructura de exchange.

La ruta más rápida para un agente:

npx skills add GemachDAO/gdex-skill --all --agent '*' -g

Luego abre gdex.pro para el terminal humano, o ejecuta el servidor MCP para que el agente pueda ejecutar operaciones por sí mismo.


Tabla de Contenidos


🤖 Instalar como Habilidad de Agente

Instala directamente en Claude Code, Cursor, Codex, Windsurf y más de 40 otros agentes usando la CLI de habilidades:

# Install all skills (recommended)
npx skills add GemachDAO/gdex-skill --all --agent '*' -g

# Pick skills interactively
npx skills add GemachDAO/gdex-skill

# Install a specific skill
npx skills add GemachDAO/gdex-skill --skill gdex-spot-trading

GDEX usa una arquitectura de múltiples habilidades — los agentes cargan solo las habilidades que necesitan, manteniendo el contexto ligero y enfocado.

Habilidades Disponibles

HabilidadDescripción
gdex-onboardingDescripción general de la plataforma, arquitectura, cadenas soportadas, inicio rápido
gdex-retailer-onboardingIntegraciones de socios minoristas — socios de incorporación con marca en la pila de GDEX
gdex-authenticationAutenticación de custodia gestionada, cifrado, claves de sesión, inicio de sesión con clave API
gdex-spot-tradingComprar/vender tokens en cualquier cadena con enrutamiento DEX
gdex-perp-tradingFuturos perpetuos HyperLiquid — posiciones, órdenes, apalancamiento
gdex-perp-fundingDepositar/retirar USDC hacia/desde HyperLiquid
gdex-limit-ordersCrear, cancelar y listar órdenes limitadas
gdex-portfolioPortafolio entre cadenas, saldos, historial de operaciones
gdex-token-discoveryDetalles de tokens, tokens en tendencia, gráficos OHLCV (sin autenticación)
gdex-token-importImportar tokens personalizados en detalles, saldos y portafolio
gdex-livestream-discoveryTokens de transmisión en vivo de Solana, estado en vivo, alertas de grandes compras
gdex-watchlist-socialListas de seguimiento, comentarios de tokens, votación de sentimiento
gdex-trending-promotionReservar espacios de tendencia pagados y verificar el estado de la reserva
gdex-xstocksListado de acciones tokenizadas (xStocks)
gdex-content-coinsMonedas de contenido Zora y monedas de creadores en Base
gdex-copy-tradingCrear/eliminar copy trade, tablas de clasificación, historial de transacciones, lista DEX (solo Solana para escrituras)
gdex-perp-copy-tradingCopy trading de perpetuos HL — traders principales, crear/gestionar configuraciones, datos de mercado
gdex-hl-outcomesMercados de resultados (eventos) HyperLiquid — listar, ordenar, gestionar posiciones
gdex-hl-referralInformación de referidos HyperLiquid y reclamos de recompensas
gdex-bridgePuente entre cadenas con cotizaciones
gdex-transfersTransferencias nativas y ERC20/SPL mediante custodia gestionada
gdex-wallet-setupGenerar billeteras EVM, claves de sesión, información de billetera (sin autenticación)
gdex-ui-install-setupConfiguración de proyectos React/Next.js, proveedores de contexto SDK, variables de entorno
gdex-ui-trading-componentsPatrones de componentes React para formularios de órdenes, tablas de posiciones, paneles de copy trade
gdex-ui-portfolio-dashboardComponentes de panel de portafolio — saldos, historial de operaciones, selectores de cadena
gdex-ui-wallet-connectionUI de conexión de billetera — botones de conexión, estado de autenticación, cambio de cadena
gdex-ui-themingTemas CSS — modo oscuro/claro, colores de trading, puntos de interrupción responsivos, Tailwind
gdex-ui-page-layoutsComposiciones de página completa — trading, portafolio, copy trading, páginas de puente
gdex-sdk-debuggingSolucionar errores — códigos de error, depuración de cifrado, peculiaridades de cadenas, trampas de HL

La description de cada habilidad le dice al agente cuándo cargarla. No se requiere configuración de clave API para las habilidades de trading (las claves compartidas están integradas).

Habilidades de Riesgo y Datos de Mercado

Fuentes de datos deterministas y eventos para riesgo e investigación. Cada una incluye un script Python de biblioteca estándar que imprime NDJSON: sin clave API, sin instalación, y cada número proviene del script, no de un modelo.

HabilidadSalida
gdex-hl-market-risk~234 perpetuos principales de HyperLiquid: funding, interés abierto, prima de oráculo, límites de apalancamiento, exclusión de listado
gdex-hl-anomalyEventos de anomalía HyperLiquid puntuados y con marca de tiempo (divergencia de oráculo, extremo de funding, shock de liquidez) contra líneas base aprendidas por mercado, más un registro de cobertura por ejecución. Backtest
gdex-token-riskPantalla de tokens GDEX en 12 cadenas: precio, liquidez, volumen, honeypot, impuestos, bloqueo de LP, concentración de tenedores (los datos de seguridad faltantes nunca son "seguros")
gvaultGVault (GMACL, Enzyme en Ethereum): NAV, precio de acción, tenencias, retorno acumulado y anualizado
python3 skills/gdex-hl-market-risk/scripts/hl_market_risk.py > hl.ndjson

Arnés de Habilidades (trae tu propia clave)

harness/ ejecuta estas habilidades con Claude en tu propia clave API de Anthropic. export produce cada fuente sin modelo; ask responde preguntas con un agente que solo puede citar cifras que los scripts de habilidades imprimieron. Cada ejecución de script se registra con un sha256 de su salida.


🔌 Servidor MCP

El servidor MCP de GDEX expone 117 herramientas — ejecución completa de trading + documentación del SDK — como herramientas del Protocolo de Contexto de Modelo. Cualquier agente de IA compatible con MCP puede operar de forma autónoma.

Código fuente: el servidor está implementado en este repositorio, en mcp-server/. El punto de entrada es mcp-server/src/index.ts y los manejadores de herramientas están en mcp-server/src/tools/. El paquete npm @gemachdao/gdex-mcp-server se construye desde ese directorio mediante el flujo de trabajo de lanzamiento. Consulta mcp-server/README.md para ejecutarlo desde el código fuente o con el Dockerfile del repositorio.

Configuración Rápida

# Auto-generate config for your AI client
npx @gemachdao/gdex-mcp-server init --client claude   # → .mcp.json
npx @gemachdao/gdex-mcp-server init --client cursor   # → .cursor/mcp.json
npx @gemachdao/gdex-mcp-server init --client vscode   # → .vscode/mcp.json
npx @gemachdao/gdex-mcp-server init --client codex    # → .codex/config.toml
npx @gemachdao/gdex-mcp-server init --client opencode  # → .opencode/mcp.json

Plugin de Claude Code

/plugin marketplace add GemachDAO/gdex-skill
/plugin install gdex@gemachdao

Instala cada habilidad de GDEX más el servidor MCP (npx -y @gemachdao/gdex-mcp-server). La clave API opcional de GDEX se guarda en tu almacén de credenciales del sistema.

Codex (OpenAI)

codex plugin marketplace add GemachDAO/gdex-skill
codex plugin add gdex@gemachdao

Instala cada habilidad de GDEX más el servidor MCP. Solo para el servidor MCP: codex mcp add gdex -- npx -y @gemachdao/gdex-mcp-server.

Extensión CLI de Gemini

gemini extensions install https://github.com/GemachDAO/gdex-skill

Configuración Manual

Agrega a la configuración MCP de tu cliente:

{
  "mcpServers": {
    "gdex-mcp-server": {
      "command": "npx",
      "args": ["@gemachdao/gdex-mcp-server"],
      "env": {
        "GDEX_API_KEY": "your-api-key"
      }
    }
  }
}

Variables de Entorno

VariableDescripciónRequerida
GDEX_API_KEYClave API de GDEX — autentica automáticamente al inicioOpcional
GDEX_API_URLSobrescribir URL base de API (predeterminado: https://trade-api.gemach.io/v1)Opcional

Herramientas de Ejecución MCP (109 herramientas)

CategoríaHerramientasDescripción
Autenticaciónauth_login, generate_session_keypair, managed_sign_in, build_sign_in_payloadInicio de sesión con clave API, claves de sesión, inicio de sesión de custodia gestionada
Trading Spotbuy_token, sell_tokenComprar/vender en Solana, Sui y 10 cadenas EVM (Ethereum, Base, Arbitrum, BSC y más)
Trading de Perpetuosopen_perp_position, place_perp_order, close_perp_position, close_all_positions, cancel_perp_order, cancel_all_perp_orders, set_leverage, perp_deposit, perp_withdrawFuturos perpetuos completos de HyperLiquid — largo/corto, TP/SL; apalancamiento hasta el límite de cada mercado (40x en BTC principal)
Datos de Perpetuosget_account_state, get_perp_positions, get_mark_price, get_all_mid_prices, get_usdc_balance, get_hl_open_orders, get_hl_trade_history, get_hl_spot_state, get_trader_leverageCuenta, posiciones y precios de HyperLiquid en tiempo real
Ejecución Directaexecute_cross_perp, execute_isolated_perp, execute_spot, direct_cancel_orderEjecución con clave privada — margen cruzado/aislado, spot, cancelar
Órdenes Limitadaslimit_buy, limit_sell, update_order, get_limit_ordersCompra/venta limitada con TP/SL, gestión de órdenes
Copy Trading (Solana)get_copy_trade_wallets, get_copy_trade_custom_wallets, get_copy_trade_gems, get_copy_trade_dexes, get_copy_trade_list, get_copy_trade_tx_list, create_copy_trade, update_copy_tradeAuto-espejo de los mejores traders de Solana
Copy Trading (Perpetuos HL)get_hl_top_traders, get_hl_top_traders_by_pnl, get_hl_user_stats, get_hl_perp_dexes, get_hl_all_assets, get_hl_clearinghouse_state, get_hl_meta_and_asset_ctxs, get_hl_deposit_tokens, get_hl_copy_trade_list, get_hl_copy_trade_tx_list, create_hl_copy_trade, update_hl_copy_tradeCopiar traders de perpetuos de HyperLiquid
Portafolio y Datosget_portfolio, get_balances, get_trade_history, get_token_details, get_trending_tokens, get_ohlcv, get_top_traders, get_wallet_info, generate_evm_walletPortafolio entre cadenas, datos de mercado, velas OHLCV
Puenteestimate_bridge, execute_bridge, get_bridge_ordersPuente de tokens nativos entre cadenas
Custodia Gestionadamanaged_purchase, managed_sell, managed_trade_status, build_trade_payloadEnvío de operaciones cifradas de bajo nivel
Transferenciastransfer_native, transfer_tokenEnviar tokens nativos y ERC20/SPL mediante custodia gestionada
Social y Listas de Seguimientoadd_comment, get_comments, vote_sentiment, get_watchlist, change_watchlistComentarios de tokens, votos de sentimiento, listas de seguimiento
Importación de Tokensimport_tokenAgregar un token personalizado para que aparezca en detalles, saldos y portafolio
Descubrimiento y Análisis de Mercadoget_newest_tokens, get_top_tokens, get_token_trades, get_token_image, get_native_prices, get_xstocks, get_zora_tokens, get_wallet_performance, get_nof1_analytics, generate_pnlTokens nuevos y principales, operaciones, precios, xStocks, monedas Zora, rendimiento de billeteras, análisis NoF1, generación de PnL
Transmisión en Vivoget_currently_live, get_live_status, get_bigbuysTokens de transmisión en vivo de Solana y alertas de grandes compras
Mercados de Resultados HLhl_outcomes, get_hl_outcome_volumes, hl_outcome_account, hl_create_outcome_order, hl_cancel_outcome_order, hl_close_outcome_orderMercados de resultados (eventos) HyperLiquid
Cuenta y Referidos HLhl_enable_trading, hl_swap_collateral, hl_tx_list, hl_list_user_copy_pnl, hl_ref_info, hl_ref_claim, hl_builder_referralHabilitación única de HL, swaps de garantía HIP-3, fills/órdenes, PnL de copy-trade, recompensas de referidos
Promoción y Sociostrending_list, trending_options, trending_register, trending_booking_status, get_retailersEspacios de tendencia pagados y socios minoristas
Cuentaoauth_login, associate_emailInicio de sesión con Google y vinculación de un correo electrónico a una billetera

Herramientas de Documentación MCP (8 herramientas)

HerramientaDescripción
search_gdex_docsBuscar documentación por palabra clave
get_sdk_patternPatrones de código TypeScript por operación
get_api_infoDetalles de endpoints de API (URL, método, parámetros)
explain_workflowFlujos de trabajo de trading paso a paso
get_chain_infoCadenas soportadas y capacidades
get_trading_guideGuías de trading spot, perpetuo o limitado
get_copy_trade_guideGuías de copy trading (Solana / HL)
get_component_guidePatrones de componentes de UI React

📦 Instalación del SDK

npm install github:GemachDAO/gdex-skill

Instala el SDK directamente desde GitHub (se compila durante la instalación). Las importaciones permanecen from '@gemachdao/gdex-skill'. Fija una versión con npm install github:GemachDAO/gdex-skill#v4.1.1. El script de instalación muestra un banner de inicio rápido en tu terminal. Dependencias opcionales entre pares para la firma de wallets (solo necesarias para la autenticación de wallet específica del usuario):

npm install ethers        # Autenticación de wallet EVM
npm install bs58 tweetnacl  # Autenticación de wallet Solana

🚀 Inicio Rápido

import { GdexSkill, GDEX_API_KEY_PRIMARY } from '@gemachdao/gdex-skill';

// 1. Create skill instance
const skill = new GdexSkill();

// 2. Authenticate with pre-configured shared key — no wallet needed
skill.loginWithApiKey(GDEX_API_KEY_PRIMARY);

// 3. Spot buy on Solana
const trade = await skill.buyToken({
  chain: 'solana',
  tokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
  amount: '0.1',   // 0.1 SOL
  slippage: 1,     // 1% max slippage
});
console.log('Trade submitted:', trade.jobId, '— status:', trade.status);

// 4. Open a BTC 10× long on HyperLiquid
const pos = await skill.openPerpPosition({
  coin: 'BTC',
  side: 'long',
  sizeUsd: '1000',
  leverage: 10,
  takeProfitPrice: '110000',
  stopLossPrice: '95000',
});

// 5. Read-only endpoints need no auth
const trending = await skill.getTrendingTokens({ chain: 'solana', period: '24h', limit: 5 });
console.log('Trending:', trending.map(t => t.symbol).join(', '));

✅ Verificación (sin conexión)

Confirma que el SDK está instalado y configurado correctamente — no se requiere conexión de red ni clave API:

npm run verify

Ejemplo de salida:

1. SDK import
  ✓  SDK imported from ../dist/index.js

2. API keys
  ✓  GDEX_API_KEY_PRIMARY   = 9b4e1c73...
  ✓  GDEX_API_KEY_SECONDARY = 2c8f0a91...
  ✓  GDEX_API_KEYS array    = 2 keys

3. GdexSkill instantiation
  ✓  new GdexSkill() — default config
  ✓  new GdexSkill({ apiUrl, timeout, maxRetries }) — custom config

4. Authentication state (offline)
  ✓  isAuthenticated() = false before login
  ✓  loginWithApiKey(GDEX_API_KEY_PRIMARY) → isAuthenticated() = true
  ✓  logout() → isAuthenticated() = false

...

  All 20 checks passed ✓
  SDK is ready — no network token required.

🔑 Autenticación

Claves API compartidas (recomendado para agentes)

Dos claves compartidas están preconfiguradas en el paquete — los agentes no necesitan firmar transacciones de wallet:

import {
  GdexSkill,
  GDEX_API_KEY_PRIMARY,
  GDEX_API_KEY_SECONDARY,
  GDEX_API_KEYS,
} from '@gemachdao/gdex-skill';

const skill = new GdexSkill();
skill.loginWithApiKey(GDEX_API_KEY_PRIMARY);  // use primary
// or:
skill.loginWithApiKey(GDEX_API_KEY_SECONDARY); // use secondary
// or cycle through them:
skill.loginWithApiKey(GDEX_API_KEYS[0]);

skill.isAuthenticated(); // → true
skill.logout();          // clear session

Nota: Los endpoints de solo lectura (getTrendingTokens, getTokenDetails, getOHLCV, getTopTraders) no requieren autenticación.

Autenticación basada en Wallet (avanzado)

Para wallets propiedad del usuario o firmantes personalizados (wallets de hardware, extensiones de navegador):

// EVM wallet (secp256k1)
await skill.authenticate({
  type: 'evm',
  address: '0xYourAddress',
  privateKey: '0xPrivateKey',
});

// Solana wallet (ed25519)
await skill.authenticate({
  type: 'solana',
  address: 'YourSolanaAddress',
  privateKey: 'base58EncodedPrivateKey',
});

// Custom signer (MetaMask / Phantom)
await skill.authenticate({
  type: 'evm',
  address: accounts[0],
  signer: async (message) =>
    window.ethereum.request({ method: 'personal_sign', params: [message, accounts[0]] }),
});

Configuración

const skill = new GdexSkill({
  apiUrl:     'https://trade-api.gemach.io/v1', // Backend (default)
  timeout:    30000,                          // Request timeout ms
  maxRetries: 3,                              // Retry attempts on 429/503
  debug:      false,                          // Log every request
});

El SDK no lee variables de entorno directamente. Si eliges usar variables de entorno, léelas en tu aplicación (por ejemplo, mediante process.env) y pasa sus valores al constructor de GdexSkill como se muestra arriba.

Variables de entorno recomendadas para tu propia aplicación:

Variable de EntornoDescripciónValor Predeterminado
GDEX_API_URLURL base del backend para pasar como apiUrlhttps://trade-api.gemach.io/v1
GDEX_API_KEYClave API para cifrado AES en el flujo de custodia gestionada—
GDEX_TIMEOUTTiempo de espera de solicitud (ms) para pasar como timeout30000
GDEX_MAX_RETRIESIntentos de reintento para pasar como maxRetries3
GDEX_DEBUGHabilitar registro de depuración para pasar como debugfalse
GDEX_CONTROL_WALLETDirección de wallet de control (userId) para custodia gestionada—
GDEX_SESSION_PRIVATEClave privada de sesión (hex, prefijo 0x) para custodia gestionada—
GDEX_MANAGED_CHAIN_IDID de cadena para operaciones gestionadas (622112261=Solana, 42161=Arbitrum para perps)622112261
CONFIRM_LIVE_TRADEEstablecer en YES para enviar operaciones reales—

🔒 Operaciones con Custodia Gestionada

Todas las operaciones en GDEX pasan por wallets gestionadas del lado del servidor. Tu wallet de control (EVM o Solana) solo se usa para autenticar (iniciar sesión) — la ejecución real en cadena la manejan los trabajadores de operaciones del backend de GDEX.

Cómo Funciona

  1. Generar un par de claves de sesión — clave secp256k1 usada para firmar operaciones después de la autenticación
  2. Iniciar sesión — la wallet de control firma un mensaje, cifrado como computedData → POST /v1/sign_in
  3. Resolver usuario — GET /v1/user con la clave de sesión cifrada para ver las wallets gestionadas
  4. Operar — codificar datos de operación en ABI, firmar con la clave de sesión, cifrar como computedData → POST /v1/purchase_v2 o /v1/sell_v2
  5. Consultar estado — GET /v1/trade-status/:requestId hasta que se complete/falla

Cifrado

Todos los payloads autenticados usan AES-256-CBC con una clave/IV determinista derivada de la clave API (sin IV aleatorio):

  • Clave = primeros 32 bytes del hex de SHA256(apiKey)
  • IV = primeros 16 bytes del hex de SHA256(SHA256(apiKey))
  • Payloads de operación/inicio de sesión: JSON.stringify({ userId, data, signature, apiKey }) → UTF-8 → cifrar → hex
  • Clave de sesión (/v1/user): bytes crudos decodificados en hex → cifrar (no cadena UTF-8)
  • La clave API se incluye dentro del payload JSON cifrado (no solo se usa para cifrar)

ADVERTENCIA: NO uses IV aleatorios ni el formato iv:ciphertext. El backend usa AES determinista derivado de la cadena hash de la clave API.

Firmas

Firmas de operaciones spot (compra/venta) usan keccak256 crudo + secp256k1 (sin prefijo EIP-191):

  • Mensaje: "<action>-<lowercaseUserId>-<dataHexWithout0x>"
  • Resumen: keccak256(utf8Bytes(message))
  • Salida: r(64 hex) + s(64 hex) + v(2 hex) = 130 caracteres, sin prefijo 0x
  • v = parámetro de recuperación crudo (00 o 01), NO EIP-155 (1b/1c)

Firmas de perps HL usan el mismo algoritmo pero con prefijos de acción específicos de HL (hl_deposit, hl_withdraw, hl_create_order, etc.) y esquemas ABI diferentes. Consulta la sección Referencia de Custodia Gestionada HL.

Firmas de inicio de sesión usan EIP-191 personal_sign con la wallet de control — esta es la ÚNICA operación que usa EIP-191. Todas las operaciones posteriores al inicio de sesión usan keccak256 crudo.

Generación de Nonce

Los nonces son generados por el cliente (no se obtienen del servidor):

const nonce = String(Math.floor(Date.now() / 1000) + Math.floor(Math.random() * 1000));

Ejemplo Rápido

import {
  GdexSkill,
  GDEX_API_KEY_PRIMARY,
  generateGdexSessionKeyPair,
  buildGdexSignInMessage,
  buildGdexSignInComputedData,
  buildGdexManagedTradeComputedData,
  buildGdexUserSessionData,
} from '@gemachdao/gdex-skill';

const skill = new GdexSkill();
skill.loginWithApiKey(GDEX_API_KEY_PRIMARY);
const apiKey = GDEX_API_KEY_PRIMARY;

// 1. Session keypair
const { sessionPrivateKey, sessionKey } = generateGdexSessionKeyPair();

// 2. Sign-in (control wallet signs this message)
const userId = '0xYourControlWallet';
const nonce = String(Math.floor(Date.now() / 1000) + Math.floor(Math.random() * 1000));
const message = buildGdexSignInMessage(userId, nonce, sessionKey);
const signature = /* wallet.signMessage(message) */;

const signInPayload = buildGdexSignInComputedData({ apiKey, userId, sessionKey, nonce, signature });
await skill.signInWithComputedData({ computedData: signInPayload.computedData, chainId: 900 });

// 3. Trade
const trade = buildGdexManagedTradeComputedData({
  apiKey, action: 'purchase', userId,
  tokenAddress: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263',
  amount: '100000',
  nonce: String(Math.floor(Date.now() / 1000) + Math.floor(Math.random() * 1000)),
  sessionPrivateKey,
});
const result = await skill.submitManagedPurchase({
  computedData: trade.computedData, chainId: 900, slippage: 1,
});

// 4. Poll
if (result.requestId) {
  const status = await skill.getManagedTradeStatus(result.requestId);
  console.log(status.status, status.hash);
}

Ayudantes de Custodia Gestionada

FunciónPropósito
generateGdexSessionKeyPair()Generar par de claves de sesión secp256k1
buildGdexSignInMessage(userId, nonce, sessionKey)Construir el mensaje de inicio de sesión para firma de wallet
encodeGdexSignInData(sessionKey, nonce, refCode?)Codificar datos de inicio de sesión en ABI (['bytes','string','string'])
buildGdexSignInComputedData({...})Construir payload de inicio de sesión cifrado
buildGdexUserSessionData(sessionKey, apiKey)Cifrar clave de sesión (bytes hex crudos) para /v1/user
encodeGdexTradeData(tokenAddr, amount, nonce?)Codificar datos de operación en ABI (['string','uint256','string'])
signGdexTradeMessageWithSessionKey(action, userId, data, privKey)Firmar operación con clave de sesión (v = recoveryParam crudo 00/01)
buildGdexManagedTradeComputedData({...})Construir payload de operación cifrado
encodeLimitOrderData(action, params)Codificar datos de orden límite en ABI (esquemas de compra/venta/actualización)
signLimitOrderMessage(action, userId, data, privKey)Firmar orden límite con clave de sesión
buildLimitOrderComputedData({...})Construir payload de orden límite cifrado
encodeCopyTradeData(action, params)Codificar datos de copy trade en ABI (crear: 12 campos, actualizar: 16 campos, chainId es uint256)
signCopyTradeMessage(action, userId, data, privKey)Firmar copy trade con clave de sesión
buildCopyTradeComputedData({...})Construir payload de copy trade cifrado
buildEncryptedGdexPayload({...})Cifrar JSON {userId, data, signature} para computedData
encryptGdexComputedData(plaintext, apiKey)Cifrar texto plano UTF-8 con AES-256-CBC
encryptGdexHexData(hexData, apiKey)Cifrar bytes crudos decodificados en hex con AES-256-CBC
decryptGdexComputedData(cipherHex, apiKey)Descifrar a texto plano UTF-8 con AES-256-CBC
deriveGdexAesMaterial(apiKey)Obtener clave/IV AES crudos de la clave API

Verificar Flujo Gestionado (sin conexión)

npm run verify:managed

Esto genera todos los payloads (par de claves de sesión, inicio de sesión, consulta de usuario, operación), valida los ciclos de cifrado/descifrado e imprime el plan de ejecución completo — sin realizar ninguna llamada API en vivo.


📚 Referencia de API

Operaciones Spot

buyToken(params)

Comprar un token en cualquier cadena compatible.

ParámetroTipoObligatorioDescripción
chainstring | ChainId✅Nombre de cadena o ID numérico
tokenAddressstring✅Dirección del contrato del token
amountstring✅Cantidad de entrada de token nativo
slippagenumber% máximo de deslizamiento (predeterminado: 1)
dexstringForzar DEX específico
walletAddressstringSobrescribir dirección de wallet
priorityFeenumberTarifa de prioridad de Solana (lamports)
const result = await skill.buyToken({
  chain: 'solana',
  tokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  amount: '0.1',
  slippage: 1,
});
// result.jobId, result.status, result.txHash, result.outputAmount

sellToken(params)

// Sell absolute amount
await skill.sellToken({ chain: 8453, tokenAddress: '0x...', amount: '100', slippage: 0.5 });

// Sell 50% of holdings
await skill.sellToken({ chain: 'solana', tokenAddress: '...', amount: '50%' });

Futuros Perpetuos (HyperLiquid)

Crítico: Los depósitos/retiros/órdenes de HyperLiquid usan un flujo criptográfico diferente al de las operaciones spot. Consulta la sección Referencia de Custodia Gestionada HL a continuación para especificaciones exactas.

openPerpPosition(params)

ParámetroTipoPredeterminadoDescripción
coinstringSímbolo del activo (p. ej., 'BTC', 'ETH')
side'long' | 'short'Dirección
sizeUsdstringColateral en USD
leveragenumber51–50×
takeProfitPricestringPrecio de TP opcional
stopLossPricestringPrecio de SL opcional
marginMode'cross' | 'isolated''cross'Modo de margen
const pos = await skill.openPerpPosition({
  coin: 'BTC', side: 'long', sizeUsd: '1000', leverage: 10,
  takeProfitPrice: '110000', stopLossPrice: '95000',
});

closePerpPosition(params)

await skill.closePerpPosition({ coin: 'BTC' });                  // close 100%
await skill.closePerpPosition({ coin: 'ETH', closePercent: 50 }); // close 50%

Otros métodos de perps

await skill.setPerpLeverage({ coin: 'BTC', leverage: 20 });

// Update leverage via HL managed-custody (explicit session-key signing)
await skill.hlUpdateLeverage({
  coin: 'BTC',
  leverage: 40,
  isCross: true,    // true = cross margin, false = isolated (default: true)
  apiKey,
  walletAddress,
  sessionPrivateKey,
});

// Deposit USDC to HyperLiquid (human-readable amount, converted internally)
await skill.perpDeposit({ amount: '10' });   // deposit 10 USDC (minimum)
await skill.perpWithdraw({ amount: '5' });    // withdraw 5 USDC

const positions = await skill.getPerpPositions({ walletAddress: '0x...' });
// Each: { coin, side, size, entryPrice, markPrice, leverage, unrealizedPnl, liquidationPrice }

Notas sobre depósitos HL: El monto está en USDC legible para humanos (p. ej., '10' para 10 USDC). El SDK convierte automáticamente a la unidad más pequeña (6 decimales). El depósito mínimo es de 10 USDC. Tu wallet gestionada debe tener el monto del depósito + el margen de tarifa del 1% en USDC en Arbitrum. Después de que la transacción en cadena se confirme, HyperLiquid tarda ~10 minutos en acreditar el depósito.

Ejecución Directa en HyperLiquid (mediante @gdexsdk/hyper-liquid-trader)

Para operar directamente en HyperLiquid L1 sin custodia gestionada — usa tu propia clave privada:

// Cross-margin perpetual trade
const result = await skill.hlExecuteCrossPerp(
  process.env.PRIVATE_KEY!,
  { coin: 'BTC', isLong: true, price: '100000', positionSize: '0.001', leverage: 10 },
);

// Isolated-margin perpetual trade
const result2 = await skill.hlExecuteIsolatedPerp(
  process.env.PRIVATE_KEY!,
  { coin: 'ETH', isLong: false, price: '3000', positionSize: '1', leverage: 5 },
);

// Spot trade on HyperLiquid
const result3 = await skill.hlExecuteSpot(
  process.env.PRIVATE_KEY!,
  { coin: 'PURR', isBuy: true, price: '0.50', size: '100' },
);

// Cancel an order directly
await skill.hlDirectCancelOrder(process.env.PRIVATE_KEY!, 'BTC', orderId);

// Get all mid prices
const mids = await skill.getHlAllMids();

// Get trade history
const trades = await skill.getHlTradeHistory('0xYourWallet');

// Get a trader's leverage context (for copy trading)
const leverage = await skill.getHlTraderLeverageContext('0xTraderWallet', 'BTC');

// Create a standalone HyperLiquidTrading instance with custom WS URLs
const trader = await skill.createHlTrader(['wss://custom-ws.example.com']);

Órdenes Límite

Endpoints: limit_buy / limit_sell / update_order / orders — NO orders/create ni orders/cancel.

// Limit buy — buy WIF when price drops to $0.50 on Solana
const buyResult = await skill.limitBuy({
  apiKey: GDEX_API_KEY_PRIMARY,
  userId: '0x53D029a671bd1CF61a2fB1F4F6e4bD830BFBb2eD',  // control wallet
  sessionPrivateKey: '<session-key-hex>',
  chainId: 622112261,           // Solana
  tokenAddress: 'EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm',
  amount: '10000000',           // lamports
  triggerPrice: '0.50',
  profitPercent: '50',          // optional: TP at 50% gain
  lossPercent: '25',            // optional: SL at 25% loss
});

// Limit sell — sell WIF when price reaches $999.99 (take-profit)
const sellResult = await skill.limitSell({
  apiKey: GDEX_API_KEY_PRIMARY,
  userId: '0x53D029a671bd1CF61a2fB1F4F6e4bD830BFBb2eD',
  sessionPrivateKey: '<session-key-hex>',
  chainId: 622112261,
  tokenAddress: 'EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm',
  amount: '100000',
  triggerPrice: '999.99',
});

// Delete/cancel an order
await skill.updateOrder({
  apiKey: GDEX_API_KEY_PRIMARY,
  userId: '0x53D029a671bd1CF61a2fB1F4F6e4bD830BFBb2eD',
  sessionPrivateKey: '<session-key-hex>',
  chainId: 622112261,
  orderId: '<64-char-hex-order-id>',
  isDelete: true,
});

// List active orders (uses session-key auth, not full computedData)
const { count, orders } = await skill.getLimitOrders({
  userId: '0x53D029a671bd1CF61a2fB1F4F6e4bD830BFBb2eD',
  data: encryptedSessionKey,  // from buildGdexUserSessionData()
  chainId: 622112261,
});

Copy Trading

Solo Solana para operaciones de escritura. El inicio de sesión debe usar chainId: 622112261. El ABI codifica chainId como uint256.

Descubrimiento (sin autenticación)

// Top 300 wallets by total PnL (cached 2 min)
const topWallets = await skill.getCopyTradeWallets();
// [{ address, totalPnl, receivedMinusSpent, spent, unrealizedValue, chainId }]

// Top 300 by net received
const customWallets = await skill.getCopyTradeCustomWallets();

// Hot new tokens from top wallets (cached 20s)
const gems = await skill.getCopyTradeGems();

// Supported DEXes for Solana
const dexes = await skill.getCopyTradeDexes(622112261);
// [{ dexName: 'pumpfun', dexNumber: 0, programId: '...' }, ...]

Lectura (autenticación con clave de sesión)

import { buildGdexUserSessionData } from '@gemachdao/gdex-skill';

const data = buildGdexUserSessionData(sessionKey, apiKey);

// List copy trade configs (cached 20s per user)
const { allCopyTrades, dexes } = await skill.getCopyTradeList({ userId, data });
// allCopyTrades: [{ copyTradeId, copyTradeName, traderWallet, isActive, lossPercent, profitPercent, ... }]

// Transaction history with PnL
const { txes } = await skill.getCopyTradeTxList({ userId, data });

Crear (autenticación computedData)

import {
  GDEX_API_KEY_PRIMARY,
  buildCopyTradeComputedData,
  generateGdexSessionKeyPair,
  buildGdexSignInMessage,
  buildGdexSignInComputedData,
} from '@gemachdao/gdex-skill';

// Sign-in MUST use chainId: 622112261 for copy trade operations
const result = await skill.createCopyTrade({
  apiKey: GDEX_API_KEY_PRIMARY,
  userId: controlWalletAddress,
  sessionPrivateKey,
  chainId: 622112261,                // Solana only
  traderWallet: 'SolanaTraderAddress',
  copyTradeName: 'Alpha Trader',
  buyMode: 1,                        // 1 = fixed SOL, 2 = percentage
  copyBuyAmount: '0.001',            // SOL amount (mode 1) or percentage (mode 2)
  lossPercent: '50',                 // stop-loss at 50%
  profitPercent: '100',              // take-profit at 100%
  copySell: true,                    // also copy sell trades
  isBuyExistingToken: false,         // skip tokens already held
  excludedDexNumbers: [],            // no DEX exclusions
});
// { isSuccess: true, message: 'created new copy trade successfully', allCopyTrades: [...] }

Eliminar (autenticación computedData)

// Delete a copy trade (isDelete: true)
const deleteResult = await skill.updateCopyTrade({
  apiKey: GDEX_API_KEY_PRIMARY,
  userId: controlWalletAddress,
  sessionPrivateKey,
  chainId: 622112261,
  copyTradeId: '<64-char-hex-id>',
  traderWallet: 'SolanaTraderAddress',
  copyTradeName: 'Alpha Trader',
  buyMode: 1,
  copyBuyAmount: '0.001',
  lossPercent: '50',
  profitPercent: '100',
  isDelete: true,                    // permanently deletes the copy trade
});
// { isSuccess: true, message: 'Updated' }

ADVERTENCIA: Tanto isDelete: true como isChangeStatus: true eliminan permanentemente el copy trade. No hay función de activar/pausar en el backend actual. Los campos booleanos usan '' para falso y '1' para verdadero internamente; la cadena '0' es verdadera en JS y activará la eliminación.

Referencia ABI de Copy Trade

AcciónCamposTipos ABI
create_copy_trade12['string','string','uint256','string'×9]
update_copy_trade16['string','string','uint256','string'×13]

Orden de campos al crear: [traderWallet, copyTradeName, chainId, gasPrice, buyMode, copyBuyAmount, isBuyExistingToken, lossPercent, profitPercent, nonce, copySell, excludedDexNumbers]

Orden de campos al actualizar: [traderWallet, copyTradeName, chainId, gasPrice, buyMode, copyBuyAmount, isBuyExistingToken, lossPercent, profitPercent, nonce, copySell, excludedDexNumbers, copyTradeId, isDelete, isChangeStatus, excludedProgramIds]

chainId en la posición 2 es uint256, todos los demás campos son string. El nonce se genera automáticamente por el SDK.


Copy Trading de Perps HL

Completamente separado del copy trading de Solana anterior. Esto copia posiciones de futuros perpetuos (largo/corto) en HyperLiquid. El inicio de sesión usa chainId: 1. Todos los campos ABI son cadenas.

Descubrimiento (sin autenticación)

// Top traders by volume/tradeCount/deposit (cached 15 min)
const topByVolume = await skill.getHlTopTraders('volume');
const topByPnl = await skill.getHlTopTradersByPnl();

// Detailed trader stats (cached 1 hr)
// NOTE: Requires MANAGED wallet address, not control wallet
const stats = await skill.getHlUserStats('0xManagedWalletAddress');
// { userStats: { '24h', '7d', '30d', dailyPnls, volumes, tradesCount, allTime } }

// Market data
const dexes = await skill.getHlPerpDexes();
const assets = await skill.getHlAllAssets();
const tokens = await skill.getHlDepositTokens();

// Account state
const state = await skill.getHlClearinghouseState('0xAddress');
const orders = await skill.getHlOpenOrdersForCopy('0xAddress');
const balance = await skill.getHlUsdcBalanceForCopy('0xAddress');

Lectura (autenticación con clave de sesión)

import { buildGdexUserSessionData } from '@gemachdao/gdex-skill';

const data = buildGdexUserSessionData(sessionKey, apiKey);

// List HL copy trade configs
const { allCopyTrades } = await skill.getHlCopyTradeList({ userId, data });
// [{ copyTradeId, copyTradeName, copyMode, traderWallet, isActive, oppositeCopy, totalPnl, ... }]

// Fill history (cached 15s, max 100 per page)
const { txes, totalCount } = await skill.getHlCopyTradeTxList({ userId, data, page: '1', limit: '20' });
// [{ coin, px, sz, side, dir, closedPnl, copyTradeName, traderWallet, ... }]

Crear (autenticación computedData)

await skill.createHlCopyTrade({
  apiKey,
  userId: controlWalletAddress,
  sessionPrivateKey,
  traderWallet: '0xTraderEvmAddress',
  copyTradeName: 'BTC Whale',
  copyMode: 1,                    // 1 = fixed USD, 2 = proportion
  fixedAmountCostPerOrder: '50',  // $50 per copied trade
  lossPercent: '25',              // mandatory, > 0 and < 100
  profitPercent: '100',           // mandatory, > 0
  oppositeCopy: false,            // true = copy opposite direction
});

Actualizar / Eliminar (autenticación computedData)

// Update parameters
await skill.updateHlCopyTrade({
  apiKey, userId: controlWalletAddress, sessionPrivateKey,
  copyTradeId: 'abc123...',
  traderWallet: '0xTraderEvmAddress',
  copyTradeName: 'Updated Name',
  copyMode: 2, fixedAmountCostPerOrder: '0.5',
  lossPercent: '30', profitPercent: '150',
  oppositeCopy: true,
});

// Delete permanently (use isDelete)
await skill.updateHlCopyTrade({ ...existingParams, isDelete: true });

// WARNING: isChangeStatus also PERMANENTLY DELETES (does NOT toggle)
await skill.updateHlCopyTrade({ ...existingParams, isChangeStatus: true });

Referencia ABI de Copy Trade de Perps HL

AcciónCamposTipos ABI
hl_create8['string' × 8]
hl_update11['string' × 11]

Orden de campos al crear: [traderWallet, copyTradeName, copyMode, fixedAmountCostPerOrder, lossPercent, profitPercent, nonce, oppositeCopy]

Orden de campos al actualizar: [traderWallet, copyTradeName, copyMode, fixedAmountCostPerOrder, lossPercent, profitPercent, nonce, isDelete, isChangeStatus, copyTradeId, oppositeCopy]

Todos los campos son string. Campos booleanos: '1' = verdadero, '' = falso. Nonce generado automáticamente por el SDK. Nota: copyMode y oppositeCopy en las respuestas contienen desplazamientos de bytes ABI (p. ej., 416), no valores reales. Tanto isDelete como isChangeStatus eliminan permanentemente la operación.


Portafolio

// Full cross-chain portfolio
const portfolio = await skill.getPortfolio({ walletAddress: '0x...' });
// { totalValueUsd, balances, perpPositions?, realizedPnl, unrealizedPnl }

// Chain-specific balances
const balances = await skill.getBalances({ walletAddress: '0x...', chain: ChainId.ETHEREUM });

// Paginated trade history
const history = await skill.getTradeHistory({
  walletAddress: '0x...', page: 1, limit: 20,
  startTime: 1700000000, endTime: 1700086400,
});

Información de Tokens

🔓 No se requiere autenticación para estos endpoints.

// Token details
const token = await skill.getTokenDetails({
  tokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  chain: 'solana',
});
// { symbol, name, priceUsd, priceChange24h, marketCap, fdv, volume24h, liquidity }

// Trending tokens
const trending = await skill.getTrendingTokens({
  chain: 'solana',
  period: '24h',     // '1h' | '6h' | '24h' | '7d'
  limit: 20,
  minLiquidity: 50000,
});

// OHLCV candles
const ohlcv = await skill.getOHLCV({
  tokenAddress: 'So11111111111111111111111111111111111111112',
  chain: 'solana',
  resolution: '60',  // '1'|'5'|'15'|'30'|'60'|'240'|'D'|'W'
  from: Math.floor(Date.now() / 1000) - 86400,
  to: Math.floor(Date.now() / 1000),
});

Mejores Traders

🔓 No se requiere autenticación.

const traders = await skill.getTopTraders({
  chain: 'solana',
  period: '7d',    // '1d' | '7d' | '30d' | 'all'
  limit: 10,
  sortBy: 'pnl',   // 'pnl' | 'winRate' | 'volume' | 'tradeCount'
});
// [{ address, totalPnlUsd, winRate, tradeCount, totalVolumeUsd }]

Puente

// Get quote first
const quote = await skill.getBridgeQuote({
  fromChain: 'solana',
  toChain: ChainId.ETHEREUM,
  tokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  amount: '100',
});
console.log('Output:', quote.outputAmount, '— fee (USD):', quote.feeUsd);

// Execute bridge
const result = await skill.bridge({
  fromChain: 'solana',
  toChain: ChainId.ETHEREUM,
  tokenAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  amount: '100',
  destinationAddress: '0xYourEthAddress',
  slippage: 0.5,
});

Información de Wallet

const info = await skill.getWalletInfo({ walletAddress: '...', chain: 'solana' });
// { address, nativeBalance, nativeSymbol, totalValueUsd, tokenCount }

Generación de Wallet

🔓 No se requiere autenticación. Las claves se generan localmente y nunca se transmiten.

Cuando un usuario aún no tiene wallet, genera una wallet de control EVM para él. Luego usa el flujo de inicio de sesión de custodia gestionada para autenticar, y el backend de Gbot aprovisiona automáticamente una wallet de trading completa — incluida una dirección de Solana y otras claves específicas de cadena — del lado del servidor. No se necesita generación separada de wallet de Solana.

generateEvmWallet() — tu wallet de control

Genera una nueva wallet compatible con EVM (Ethereum, Base, Arbitrum, BSC, etc.) usando ethers.Wallet.createRandom().

import {
  GdexSkill,
  generateEvmWallet,
  generateGdexSessionKeyPair,
  buildGdexSignInMessage,
  GDEX_API_KEY_PRIMARY,
} from '@gemachdao/gdex-skill';

// Step 1: generate your EVM control wallet (one-time setup)
const wallet = generateEvmWallet();
console.log(wallet.address);  // '0xAbCd...' (checksummed) — safe to share
// ⚠️  Store wallet.privateKey and wallet.mnemonic securely

// Step 2: generate a session keypair for managed-custody trading
const { sessionPrivateKey, sessionKey } = generateGdexSessionKeyPair();

// Step 3: build the sign-in message and sign with your control wallet
const message = buildGdexSignInMessage(wallet.address, String(Date.now()), sessionKey);
// Sign with: new ethers.Wallet(wallet.privateKey).signMessage(message)

// Step 4: submit sign_in computedData (see Managed-Custody Trading section above)
// The backend provisions Solana + all other trading wallets server-side

🌐 Cadenas Compatibles

CadenaChainIdToken nativoDEXes
Ethereum1ETHUniswap V2/V3, Odos
Optimism10ETHUniswap V3, Odos
BNB Smart Chain56BNBPancakeSwap, Odos
Sonic146S—
Fraxtal252frxETHUniswap V3
Nibiru6900NIBI—
Base8453ETHUniswap V3, Odos, Arcadia
Arbitrum One42161ETHUniswap V3, Odos
Berachain80094BERA—
Solana622112261SOLRaydium, Raydium V2, Orca
Sui1313131213SUICetus, Bluefin
HyperLiquidsolo perpsUSDCMotor de perps nativo

El enum ChainId es más amplio que esta tabla. También define Avalanche (43114), Polygon (137), zkSync Era (324), Linea (59144), Blast (81457) y Scroll (534352). El supportedChainIds del backend no los incluye, por lo que las llamadas contra esos ids no se enrutarán. Opera solo con las cadenas listadas arriba.

import { ChainId } from '@gemachdao/gdex-skill';

ChainId.ETHEREUM   // 1
ChainId.OPTIMISM   // 10
ChainId.BSC        // 56
ChainId.SONIC      // 146
ChainId.FRAXTAL    // 252
ChainId.NIBIRU     // 6900
ChainId.BASE       // 8453
ChainId.ARBITRUM   // 42161
ChainId.BERACHAIN  // 80094
ChainId.SOLANA     // 622112261
ChainId.SUI        // 1313131213

⚠️ Manejo de Errores

import {
  GdexAuthError,       // 401/403 — re-authenticate
  GdexValidationError, // invalid input params
  GdexApiError,        // 4xx/5xx backend errors
  GdexNetworkError,    // connection failures, timeouts
  GdexRateLimitError,  // 429 — check err.retryAfter
} from '@gemachdao/gdex-skill';

try {
  await skill.buyToken({ ... });
} catch (err) {
  if (err instanceof GdexRateLimitError) {
    console.log(`Rate limited — retry after ${err.retryAfter}s`);
    await new Promise(r => setTimeout(r, err.retryAfter * 1000));
    // retry…
  } else if (err instanceof GdexAuthError) {
    skill.loginWithApiKey(GDEX_API_KEY_PRIMARY); // re-auth
  } else if (err instanceof GdexValidationError) {
    console.error(`Bad param "${err.field}": ${err.message}`);
  } else if (err instanceof GdexApiError) {
    console.error(`API ${err.statusCode}: ${err.message}`);
  } else if (err instanceof GdexNetworkError) {
    console.error(`Network (${err.code}): ${err.message}`);
  }
}
ClaseCuándo se lanza
GdexAuthError401/403, credenciales inválidas
GdexValidationErrorDirección, monto, cadena o slippage inválidos
GdexApiErrorHTTP no exitoso (4xx/5xx)
GdexNetworkErrorConexión rechazada, ECONNABORTED, timeout
GdexRateLimitErrorHTTP 429 (tiene .retryAfter en segundos)

🛠 Funciones de Utilidad

import {
  getChainName,         // getChainName(8453)        → "Base"
  getNativeToken,       // getNativeToken('solana')   → "SOL"
  formatTokenAmount,    // formatTokenAmount('1000000', 6, 'USDC') → "1 USDC"
  formatUsd,            // formatUsd('1234.5')         → "$1,234.50"
  formatPercentChange,  // formatPercentChange('5.23') → "+5.23%"
  shortenAddress,       // shortenAddress('0x1234...') → "0x1234...5678"
  validateAddress,      // throws GdexValidationError if invalid
  validateAmount,       // throws GdexValidationError if invalid
  validateChain,        // throws GdexValidationError if unsupported
} from '@gemachdao/gdex-skill';

🧪 Pruebas

Las 103 pruebas se ejecutan con HTTP simulado — no se requiere clave API real ni conexión de red:

npm test              # run all 103 tests
npm run test:coverage # with coverage report
npm run verify        # offline SDK smoke-test (20 checks)
npm run verify:managed # managed-custody payload validation (dry-run)

Suites de pruebas:

  • tests/client/auth.test.ts — autenticación con clave API, firma de wallets EVM/Solana
  • tests/actions/spotTrade.test.ts — compra/venta, slippage, validación
  • tests/actions/perpTrade.test.ts — apertura/cierre de posiciones, apalancamiento, depósitos
  • tests/actions/portfolio.test.ts — saldos, historial, información de wallet
  • tests/actions/tokenInfo.test.ts — tendencias, OHLCV, detalles de tokens, mejores traders
  • tests/utils/walletGeneration.test.ts — generación de wallet de control EVM (offline)
  • tests/utils/gdexManagedCrypto.test.ts — helpers de cripto con custodia gestionada (AES, firma, codificación ABI)

🏗 Arquitectura

AI Agent (Claude Code / Cursor / Codex / ...)
   │
   │  npx skills add GemachDAO/gdex-skill
   │  ──────────────────────────────────
   │  SKILL.md → agent skill directory
   │
   ▼
@gemachdao/gdex-skill  (this package)
   │  TypeScript methods with full type safety
   │  @gdexsdk/hyper-liquid-trader for HyperLiquid L1 queries & direct execution
   │  Managed-custody: AES-256-CBC encryption + secp256k1 session signing
   │  computedData payloads for all trade operations
   │  Auto-retry with exponential backoff
   │
   │  Control Wallet (EVM / Solana)
   │  └─ signs once for /v1/sign_in → session keypair
   │
   ▼
Gbot Backend API  (https://trade-api.gemach.io/v1)
   │  Decrypt computedData → verify signature → resolve nonce (gRPC)
   │  NATS JetStream trade queue
   │  Server-side managed wallets (custody)
   │  DEX aggregation engine
   ▼
Blockchains  (Solana · Sui · Ethereum · Base · Arbitrum · …)

Referencia de Custodia Gestionada HL

Las operaciones de perps en HyperLiquid usan un pipeline criptográfico distinto al de los trades al contado. Cualquier detalle incorrecto produce un error 400 Unauthorized (code 103). Esta sección documenta la especificación exacta.

Flujo de Depósito HL

El backend ejecuta custodialmente el depósito on-chain: carga la clave privada del usuario en el servidor, construye una transacción de Arbitrum y envía USDC al receptor del puente de HyperLiquid. El agente solo proporciona una firma de autorización.

Agent SDK                              Backend
────────                               ───────
1. ABI-encode deposit params     ──►   2. AES-decrypt computedData
   (uint64 chainId, address,           3. ABI-decode data
    uint256 amount, string nonce)       4. Verify chainId == 42161
2. Sign with session key          ──►  5. Verify signature vs stored sessionKey
3. AES-encrypt as computedData    ──►  6. Validate token, balance, min deposit
4. POST /v1/hl/deposit                 7. Execute ERC-20 transfer on Arbitrum

Esquemas ABI HL (CRÍTICO)

AcciónTipos ABICampos
hl_deposit['uint64', 'address', 'uint256', 'string'][chainId, tokenAddress, amount, nonce]
hl_withdraw['string', 'string'][amount, nonce]
hl_create_order['string', 'bool', 'string', 'string', 'bool', 'string', 'string', 'string', 'bool'][coin, isLong, price, size, reduceOnly, nonce, tpPrice, slPrice, isMarket]
hl_place_order['string', 'bool', 'string', 'string', 'bool', 'string'][coin, isLong, price, size, reduceOnly, nonce]
hl_close_all['string'][nonce]
hl_cancel_order['string', 'string', 'string'][nonce, coin, orderId]
hl_cancel_all_orders['string'][nonce]
hl_update_leverage['string', 'uint32', 'bool', 'string'][coin, leverage, isCross, nonce]

ADVERTENCIA: El chainId hl_deposit usa uint64, NO uint256. Esta es la causa más común de errores "Unauthorized". El backend re-codifica con uint64 para la verificación de firma — si codificas con uint256, el hex difiere, la recuperación de firma falla y obtienes el código 103.

Formato de Firma HL

Todas las operaciones de escritura HL firman con la clave privada de sesión (del sign-in), NO con la clave de la wallet de control:

// Message format (no EIP-191 prefix):
const msg = `${action}-${userId.toLowerCase()}-${dataHex}`;
// e.g.: "hl_deposit-0x53d029a6...-00000000000000000000000000000000000000000000000000000000..."

const digest = keccak256(toUtf8Bytes(msg));
const sig = new SigningKey(sessionPrivateKey).sign(digest);
// Output: r(64hex) + s(64hex) + v(2hex) = 130 chars, no 0x prefix
// v = raw recovery parameter (00 or 01), NOT EIP-155 (1b/1c)

Restricciones de Depósito HL

RestricciónValor
CadenaSolo Arbitrum (chainId 42161)
TokenSolo USDC (0xaf88d065e77c8cC2239327C5EDb3A432268e5831)
MontoEn la unidad más pequeña (6 decimales): 10 USDC = 10000000
Depósito mínimo10 USDC
Buffer de comisiónEl saldo debe cubrir amount × 1.01
Tiempo de entrega~10 minutos después de que la tx de Arbitrum confirme
Receptor del puente0x2Df1c51E09aECF9cacB7bc98cB1742757f163dF7
userIdDirección de la wallet de control (del sign-in), NO la wallet gestionada

Códigos de Error HL

CódigoErrorCausa
101Parámetros faltantescomputedData no está en el cuerpo de la solicitud
102chainId inválidochainId no es 42161
102Parámetros inválidosNonce ya usado, o token no soportado
103No autorizadoFalló la verificación de firma — revisa los tipos ABI (uint64!), userId, y que estés firmando con la clave de sesión registrada durante el sign-in
—Saldo insuficienteLa wallet gestionada no tiene suficiente USDC + comisión en Arbitrum
—Monto demasiado bajoMonto < 10 USDC

Encabezados HTTP (Requeridos)

El backend está detrás de Cloudflare. Las solicitudes DEBEN incluir encabezados similares a los de un navegador:

{
  'Content-Type': 'application/json',
  'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
  'Accept': 'application/json',
  'Accept-Language': 'en-US,en;q=0.9',
  'Accept-Encoding': 'gzip, deflate, br',
  'Connection': 'keep-alive',
  'Authorization': 'Bearer <apiKey>',  // NOT X-API-Key
}

ADVERTENCIA: Usar un User-Agent que no sea de navegador (p. ej., axios/1.x o cualquier cadena que contenga identificadores de bot) resultará en un 403 de Cloudflare "Access denied". El SDK maneja esto automáticamente.

Ejemplo Completo de Depósito HL

import {
  GdexSkill,
  GDEX_API_KEY_PRIMARY,
  generateGdexSessionKeyPair,
  buildGdexSignInMessage,
  buildGdexSignInComputedData,
  buildHlComputedData,
} from '@gemachdao/gdex-skill';
import { ethers } from 'ethers';

const apiKey = GDEX_API_KEY_PRIMARY;
const skill = new GdexSkill();
skill.loginWithApiKey(apiKey);

// 1. Generate session keypair
const { sessionPrivateKey, sessionKey } = generateGdexSessionKeyPair();

// 2. Sign in (control wallet signs the Terms message)
const controlWallet = new ethers.Wallet('0xYourPrivateKey');
const nonce = String(Date.now());
const message = buildGdexSignInMessage(controlWallet.address, nonce, sessionKey);
const signature = await controlWallet.signMessage(message);

const signInPayload = buildGdexSignInComputedData({
  apiKey, userId: controlWallet.address, sessionKey, nonce,
  signature: signature.replace(/^0x/, ''),
});
await skill.signInWithComputedData({
  computedData: signInPayload.computedData, chainId: 42161,
});

// 3. Deposit USDC (amount in smallest unit, uint64 chainId is handled by SDK)
const computedData = buildHlComputedData({
  action: 'hl_deposit',
  apiKey,
  walletAddress: controlWallet.address,  // userId = control wallet
  sessionPrivateKey,
  actionParams: {
    chainId: 42161,
    tokenAddress: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
    amount: '10000000',  // 10 USDC in smallest unit (6 decimals)
  },
});

const result = await skill.client.post('/v1/hl/deposit', { computedData });
// { hash: '0x...', isSuccess: true, amount: '10000000', message: 'Deposit successfully...' }
// Wait ~10 minutes for HyperLiquid to credit the deposit

Contribuciones

  1. Haz un fork del repositorio
  2. Crea una rama de funcionalidad
  3. Añade pruebas para la nueva funcionalidad
  4. Ejecuta npm test && npm run build && npm run verify
  5. Envía un pull request

Licencia

MIT © GemachDAO