Skip to main content

AI Agent Patterns for Gala Launchpad MCP Server

This guide provides AI agents with common workflows, gotchas, and best practices when using the galachain-launchpad MCP server.

Table of Contents​


Common Workflows​

1. Token Launch Workflow​

Complete token creation from scratch:

// Step 1: Verify token name is available
gala_launchpad_check_token_name({
tokenName: 'mytoken'
})
// Response: { available: true, message: "Token name is available" }

// Step 2: Verify token symbol is available
gala_launchpad_check_token_symbol({
symbol: 'MTK'
})
// Response: { available: true, message: "Token symbol is available" }

// Step 3: Upload token image (optional, can use URL instead)
gala_launchpad_upload_token_image({
tokenName: 'mytoken',
imagePath: '/absolute/path/to/image.png'
})
// Response: { url: 'https://launchpad.galachain.com/uploads/mytoken.png' }

// Step 4: Launch the token
gala_launchpad_launch_token({
tokenName: 'mytoken',
tokenSymbol: 'MTK',
tokenDescription: 'My awesome token for the community',
tokenImage: 'https://launchpad.galachain.com/uploads/mytoken.png',
preBuyQuantity: '100', // Optional initial buy
websiteUrl: 'https://mytoken.com',
twitterUrl: 'https://twitter.com/mytoken'
})
// Response: { tokenName: 'mytoken', transactionId: '...' }

// Step 5: Get the frontend URL
gala_launchpad_get_url_by_token_name({
tokenName: 'mytoken'
})
// Response: { url: 'https://launchpad.galachain.com/token/mytoken' }

2. Trading Workflow (Buy Tokens)​

Two-step process: Calculate → Execute

// Step 1: Calculate buy amount (REQUIRED FIRST STEP)
const calcResult = gala_launchpad_calculate_buy_amount({
tokenName: 'woohoo',
amount: '10', // Spending 10 GALA
type: 'native' // 'native' = GALA amount
})
// Response: {
// amount: '16843.7579794843252', // <- THIS is expectedAmount for buy()
// reverseBondingCurveFee: '0.059280156', // <- THIS is maxAcceptableReverseBondingCurveFee
// transactionFee: '0.00141090',
// gasFee: '1'
// }

// Step 2: Execute buy with calculated expectedAmount AND reverseBondingCurveFee
gala_launchpad_buy({
tokenName: 'woohoo',
amount: '10', // Same as Step 1
type: 'native', // Same as Step 1
expectedAmount: '16843.7579794843252', // <- Use result.amount from Step 1
maxAcceptableReverseBondingCurveFee: '0.059280156', // <- Use result.reverseBondingCurveFee from Step 1
slippageToleranceFactor: 0.05 // 5% slippage protection
})
// Response: { transactionId: '...', status: 'completed' }

// Step 3: Verify trade completed
gala_launchpad_fetch_trades({
tokenName: 'woohoo',
userAddress: 'eth|your-address',
pageSize: 1
})

⚠️ CRITICAL:

  • expectedAmount must be result.amount from calculate function, NOT your input amount!
  • maxAcceptableReverseBondingCurveFee must be result.reverseBondingCurveFee from calculate function!

3. Trading Workflow (Sell Tokens)​

Same two-step pattern:

// Step 1: Calculate sell amount
const calcResult = gala_launchpad_calculate_sell_amount({
tokenName: 'woohoo',
amount: '1000', // Selling 1000 tokens
type: 'exact' // 'exact' = exact token amount
})
// Response: {
// amount: '5.234567', // <- THIS is expectedAmount for sell()
// reverseBondingCurveFee: '2.617284', // <- THIS is maxAcceptableReverseBondingCurveFee
// transactionFee: '0.00523457',
// gasFee: '1'
// }

// Step 2: Execute sell with calculated expectedAmount AND reverseBondingCurveFee
gala_launchpad_sell({
tokenName: 'woohoo',
amount: '1000',
type: 'exact',
expectedAmount: '5.234567', // <- Use result.amount from Step 1
maxAcceptableReverseBondingCurveFee: '2.617284', // <- Use result.reverseBondingCurveFee from Step 1
slippageToleranceFactor: 0.05
})

4. Portfolio Management Workflow​

Check balances and trading activity:

// Get GALA balance
gala_launchpad_fetch_gala_balance({
address: 'eth|your-address' // Optional, defaults to authenticated wallet
})

// Get specific token balance (optimized single-token lookup)
gala_launchpad_fetch_token_balance({
tokenName: 'woohoo',
address: 'eth|your-address'
})

// Get all tokens held (with filtering)
gala_launchpad_fetch_tokens_held({
address: 'eth|your-address',
tokenName: 'woohoo', // Optional exact match filter
pageSize: 20 // Max 20 for user operations
})

// Get all tokens created by user
gala_launchpad_fetch_tokens_created({
address: 'eth|your-address',
search: 'test', // Optional backend search; tokenName is exact-matched on the returned page
pageSize: 20
})

// Get trade history
gala_launchpad_fetch_trades({
tokenName: 'woohoo',
userAddress: 'eth|your-address',
tradeType: 'BUY', // Optional: 'BUY' or 'SELL'
pageSize: 20, // Max 20 for trade operations
sortOrder: 'DESC'
})

5. Token Lock/Unlock Workflow​

Lock tokens for staking, escrow, or vesting:

// ============================================================================
// LOCK TOKENS - Basic staking (batch operation: tokens is always an array)
// ============================================================================

// Lock tokens (caller becomes lock authority by default)
gala_launchpad_lock_tokens({
tokens: [{ tokenName: 'anime', amount: '1000' }]
})
// Response: { transactionId: '...', status: 'completed' }

// ============================================================================
// LOCK TOKENS - Advanced options (escrow, vesting)
// ============================================================================

// Lock with custom authority (escrow pattern)
gala_launchpad_lock_tokens({
tokens: [{
tokenName: 'anime',
amount: '500',
lockAuthority: 'eth|1234...', // Escrow agent can unlock
name: 'escrow-order-001' // Identifier for matching during unlock
}]
})

// Lock with expiration (vesting/staking period)
gala_launchpad_lock_tokens({
tokens: [{
tokenName: 'anime',
amount: '10000',
name: 'vesting-q1-2025',
expires: 1743465600000 // April 1, 2025 timestamp (auto-unlock)
}]
})

// ============================================================================
// UNLOCK TOKENS - Release locked tokens (batch operation: tokens is always an array)
// ============================================================================

// Basic unlock (must be called by lock authority)
gala_launchpad_unlock_tokens({
tokens: [{ tokenName: 'anime', amount: '500' }]
})
// Response: { transactionId: '...', status: 'completed' }

// Unlock with name matching (for specific locks)
gala_launchpad_unlock_tokens({
tokens: [{ tokenName: 'anime', amount: '1000', name: 'escrow-order-001' }] // Match the lock name
})

⚠️ CRITICAL:

  • lockAuthority defaults to caller - only the authority can unlock
  • name parameter helps identify specific locks when unlocking
  • expires timestamp enables auto-unlock after the specified time
  • Only the lock authority can call unlock_tokens

6. Backend-Proxy Trading Quotes (Fast, No Chain Call)​

Get instant quotes and fee info without hitting GalaChain:

These tools use backend-proxied endpoints with local bonding curve math. No GalaChain network round-trip — results are instant. Useful for UI price previews, quoting UIs, and pre-flight checks.

// Fetch current launchpad fee (cached 1 hour)
const fee = gala_launchpad_fetch_launchpad_fee()
// Response: 25 (number — fee in GALA)

// Fetch sale details for a token (cached 10 seconds)
const details = gala_launchpad_fetch_sale_details({ tokenName: 'anime' })
// Response: {
// maxSupply: '10000000',
// sellingTokenQuantity: '8500000',
// nativeTokenQuantity: '4250.5',
// saleStatus: 'ACTIVE',
// saleStartTime: undefined
// }

// Get a buy quote (NATIVE → MEME): how many tokens for 100 GALA?
const buyQuote = gala_launchpad_get_trade_quote({
tokenName: 'anime',
amount: '100', // 100 GALA to spend
type: 'NATIVE', // Input is GALA
method: 'IN', // Spending this amount
})
// Response: {
// amount: '51234.567', // tokens you will receive
// reverseBondingCurveFee: '0', // dynamic pool fee
// transactionFee: '0.001234',
// gasFee: '1'
// }

// Get a sell quote (MEME → NATIVE): how much GALA for 1000 tokens?
const sellQuote = gala_launchpad_get_trade_quote({
tokenName: 'anime',
amount: '1000', // 1000 tokens to sell
type: 'MEME', // Input is the meme token
method: 'IN', // Selling this amount
})

// Pre-mint quote during token creation (supply = 0 assumed)
const premintQuote = gala_launchpad_get_premint_quote({
amount: '500', // 500 GALA to spend at launch
})
// Response: {
// amount: '321000.123', // tokens you will receive at launch
// ...
// }

When to use backend-proxy tools vs chain-call tools:

ScenarioRecommended Tool
Price preview / UI displaygala_launchpad_get_trade_quote (instant)
Pre-trade validation (accurate)gala_launchpad_calculate_buy_amount (chain)
Token creation previewgala_launchpad_get_premint_quote
Token sale status checkgala_launchpad_fetch_sale_details
Fee displaygala_launchpad_fetch_launchpad_fee

7. Pool Analysis Workflow​

Discover and analyze token pools:

// Fetch recent/trending pools
gala_launchpad_fetch_pools({
type: 'trending', // 'recent', 'trending', or 'user'
pageSize: 100 // Max 100 for pool operations
})

// Get detailed pool state
gala_launchpad_fetch_pool_details({
tokenName: 'woohoo'
})

// Get holder distribution
gala_launchpad_fetch_token_distribution({
tokenName: 'woohoo'
})

// Get volume data for charting
gala_launchpad_fetch_volume_data({
tokenName: 'woohoo',
resolution: '1h', // '1m', '5m', '15m', '1h', '4h', '1d'
from: '2024-01-01T00:00:00Z',
to: '2024-01-31T23:59:59Z'
})

8. GSwap DEX Swap Workflow (queued RequestTrade)​

Quote, submit the queued request, inspect the applied result, and verify assets:

// Step 1: Get a fresh quote
const quote = gala_launchpad_get_swap_quote_exact_input({
fromToken: 'GALA',
toToken: 'GUSDC',
amount: '100',
})

// Step 2: Execute the queued RequestTrade; the tool waits for apply
const swap = gala_launchpad_execute_swap({
fromToken: 'GALA',
toToken: 'GUSDC',
inputAmount: '100',
estimatedOutput: quote.estimatedOutput,
feeTier: quote.feeTier,
slippageTolerance: 0.01,
})

// Step 3: Read the applied trade, not the queued submission, for execution details
const applied = swap.confirmation
console.log(applied.result) // token quantities, fee, and fee breakdown

// Step 4: Verify the resulting wallet assets
gala_launchpad_get_swap_user_assets({ walletAddress: 'eth|your-address' })

The response includes a queued submission (method: 'RequestTrade', uniqueKey, request transactionId, and mode: 'queued') plus the applied confirmation. If the outcome is unknown, use the unique key with gala_launchpad_get_swap_result; never submit the swap again.


Critical Gotchas​

Gotcha #1: Missing reverseBondingCurveFee Parameter ⚠️🔥​

Problem: AI agents forget to pass maxAcceptableReverseBondingCurveFee, causing transaction failures.

Wrong:

// Step 1: Calculate
const calc = gala_launchpad_calculate_sell_amount({ tokenName: 'anime', amount: '500', type: 'exact' })
// calc = { amount: '0.7056532', reverseBondingCurveFee: '0.3528266', ... }

// Step 2: Execute - MISSING reverseBondingCurveFee!
gala_launchpad_sell({
tokenName: 'anime',
amount: '500',
type: 'exact',
expectedAmount: '0.7056532', // ✅ Got this right
// ❌ MISSING: maxAcceptableReverseBondingCurveFee
slippageToleranceFactor: 0.05
})
// Result: Transaction fails with "FAILED" status

Correct:

// Step 1: Calculate
const calc = gala_launchpad_calculate_sell_amount({ tokenName: 'anime', amount: '500', type: 'exact' })
// calc = { amount: '0.7056532', reverseBondingCurveFee: '0.3528266', ... }

// Step 2: Execute - Include BOTH parameters from calculation
gala_launchpad_sell({
tokenName: 'anime',
amount: '500',
type: 'exact',
expectedAmount: '0.7056532', // ✅ From result.amount
maxAcceptableReverseBondingCurveFee: '0.3528266', // ✅ From result.reverseBondingCurveFee
slippageToleranceFactor: 0.05
})
// Result: Transaction succeeds!

Fix: Always extract BOTH result.amount AND result.reverseBondingCurveFee from calculate functions, then pass BOTH to buy/sell.

This applies to both buy AND sell operations!

Gotcha #2: expectedAmount Parameter Confusion ⚠️​

Problem: AI agents use the input amount as expectedAmount, causing WebSocket timeouts.

Wrong:

gala_launchpad_buy({
amount: '10',
expectedAmount: '10' // ❌ WRONG - This is your input, not the expected output!
})

Correct:

// Step 1: Calculate first
const calc = gala_launchpad_calculate_buy_amount({ amount: '10', ... })
// calc.amount = '16843.7579794843252'

// Step 2: Use calc.amount as expectedAmount
gala_launchpad_buy({
amount: '10',
expectedAmount: '16843.7579794843252' // ✅ CORRECT - Use result.amount
})

Fix: Always call calculate*Amount() first, then use result.amount as expectedAmount.

Gotcha #3: Limit Validation Errors​

Problem: AI agents hit "Limit must be between 1 and 20" errors when using pageSize: 100.

Root Cause: Different operations have different maximum page sizes (the pageSize argument):

  • Trade operations: Max 20
  • User operations (tokens held/created): Max 20
  • Pool operations: Max 100
  • Comment operations: Max 50

Wrong:

gala_launchpad_fetch_trades({
pageSize: 100 // ❌ WRONG - Trades max is 20!
})

Correct:

gala_launchpad_fetch_trades({
pageSize: 20 // ✅ CORRECT - Respects constraint
})

gala_launchpad_fetch_pools({
pageSize: 100 // ✅ CORRECT - Pools allow 100
})

Fix: Use the constraint reference table below for correct limits.

Gotcha #4: Type Parameter Ambiguity​

Problem: Confusion between type: 'native' and type: 'exact'.

When to use 'native' (GALA amount):

  • "I want to spend 10 GALA" → { amount: '10', type: 'native' }
  • "I want to receive 5 GALA" → { amount: '5', type: 'native' }

When to use 'exact' (exact token amount):

  • "I want to buy exactly 1000 tokens" → { amount: '1000', type: 'exact' }
  • "I want to sell exactly 500 tokens" → { amount: '500', type: 'exact' }

Most Common: Use 'native' when you know the GALA amount.

Gotcha #5: Token Filtering Confusion​

Problem: Not using the right filter for the task.

Use tokenName for exact lookups:

gala_launchpad_fetch_tokens_held({
tokenName: 'anime', // Exact match
pageSize: 1 // Only need 1 result
})

Use search for discovery:

gala_launchpad_fetch_tokens_held({
search: 'dragon', // Fuzzy search
pageSize: 10 // Get multiple matches
})

For created-token results, search is applied by the backend and tokenName is exact-matched locally on the returned page. If both are provided, both filters apply.

Gotcha #6: Wallet Address Format​

Problem: A wallet address in a form the SDKs do not take is refused before anything is signed or sent.

Forms a tool accepts (pass the address as you have it; never convert by hand):

  • ✅ eth|<40 hex digits> - the GalaChain form of an Ethereum account (the SDK sends the EIP-55 checksummed spelling)
  • ✅ 0x<40 hex digits> - a bare Ethereum address, converted by the SDK
  • ✅ client|<id> - a GalaChain alias, sent as written
  • ❌ eth|0x<40 hex digits> - not an address form: refused with INVALID_ETH_USER_REF_PREFIX; an eth| reference takes the 40 digits with no 0x (the error's expected names the right spelling)
  • ❌ a mixed-case address whose EIP-55 checksum is wrong is refused (Invalid address checksum)

Gotcha #7: Swap outcome unknown — never resubmit​

Problem: A timeout or dispatch response does not prove whether the queued swap applied.

CONFIRMATION_TIMEOUT and SUBMISSION_OUTCOME_UNKNOWN mean the outcome is unknown. A 409 CHAIN_DISPATCH_FAILED also means the uniqueKey was consumed and must be recovered the same way:

// Use the uniqueKey from the execute_swap response or error
gala_launchpad_get_swap_result({
uniqueKey: 'swap_abc123',
timeoutMs: 30000,
})

Never resubmit while the outcome is unknown. Resolve the persisted key first; the result is either the applied confirmation or a terminal chain rejection.

How the server picks the tip (8.0.1): DEX errors are classified by the gswap-sdk error code (shown in the error text as [CODE]), never by English message text, which may change or be localized. The "outcome unknown, do NOT resubmit" tip covers every code gswap-sdk's mayHaveBeenQueued treats as unknown: SUBMISSION_OUTCOME_UNKNOWN, CONFIRMATION_TIMEOUT, CONFIRMATION_ABORTED, CONFIRMATION_FAILED, CONFIRMATION_MALFORMED, CONFIRMATION_KEY_MISMATCH, GATEWAY_REPORTED_ERROR, GATEWAY_DATA_MISSING, GATEWAY_MODE_INVALID, GATEWAY_SYNC_REQUEST_TRADE, MISSING_UNIQUE_KEY, UNIQUE_KEY_MISMATCH, and CHAIN_DISPATCH_FAILED with status 409, 5xx or none. CHAIN_REJECTED (and a 422 dispatch) means the swap did not execute (slippage is recognised from the chain's message text); gateway refusals (SIGNATURE_INVALID, DTO_INVALID, RATE_LIMITED, ...) mean nothing was queued; SIGNING_FAILED / KEY_PROVIDER_FAILED / TOKEN_RESOLUTION_FAILED mean nothing was sent. Once execute_swap / get_swap_result hold a queued swap's uniqueKey, every failure except a chain rejection is reported as outcome unknown (never "submit a new request"). Errors without a recognised code (gswap-sdk 1.1.x, other tools) fall back to message patterns.

Gotcha #8: DEX slippage rejection​

Problem: The chain rejects the request at apply time when the output falls below the minimum: VALIDATION_FAILED: Slippage limit: trade would return ….

Re-quote immediately and pass the fresh estimatedOutput and feeTier to gala_launchpad_execute_swap. The rejected request's uniqueKey is consumed and the swap did not execute, so a new request is safe.


Constraint Reference​

Pagination Limits by Operation Type​

Operation TypeMax pageSizeTool
Trade Operations20gala_launchpad_fetch_trades
User Operations20gala_launchpad_fetch_tokens_held, gala_launchpad_fetch_tokens_created
Pool Operations100gala_launchpad_fetch_pools

Each tool's schema publishes its own maximum (maximum of pageSize); the server rejects a larger value.

Common Validation Rules​

ParameterPatternExample
tokenName^[a-zA-Z0-9]{1,25}$'mytoken', 'TestToken1'
tokenSymbol^[A-Z0-9]{2,10}$'MTK', 'TEST123'
address`^(0x[a-fA-F0-9]{40}|eth\[a-fA-F0-9]{40})$`
amount^[0-9.]+$'10', '100.5'
slippageTolerance0-1 (decimal)0.05 (5%), 0.01 (1%)

Error Troubleshooting​

"Limit must be a number between 1 and 20"​

Cause: Using pageSize: 100 on trade or user operations.

Solution:

// Wrong
gala_launchpad_fetch_trades({ pageSize: 100 })

// Correct
gala_launchpad_fetch_trades({ pageSize: 20 })

"WebSocket timeout on trade execution"​

Cause: Using wrong expectedAmount (likely using input amount instead of calculated result).

Solution:

// Wrong
const calc = gala_launchpad_calculate_buy_amount({ amount: '10', ... })
gala_launchpad_buy({ amount: '10', expectedAmount: '10' })

// Correct
const calc = gala_launchpad_calculate_buy_amount({ amount: '10', ... })
gala_launchpad_buy({ amount: '10', expectedAmount: calc.amount })

"Token name validation failed"​

Cause: Token name doesn't match pattern ^[a-zA-Z0-9]{1,25}$.

Valid: 'mytoken', 'TestToken', 'token123' Invalid: 'my-token' (dash), 'my token' (space), a 26-character name (too long)

Solution: Use letters and digits only, 1-25 characters.

"Token symbol validation failed"​

Cause: Token symbol doesn't match pattern ^[A-Z0-9]{2,10}$.

Valid: 'MTK', 'TEST123', 'ABC' Invalid: 'mtk' (lowercase), 'A' (too short), 'MY-TOKEN' (dash)

Solution: Use uppercase alphanumeric only, 2-10 characters.

"At least one social URL required"​

Cause: Launching token without websiteUrl, twitterUrl, or telegramUrl.

Solution: Provide at least one social link:

gala_launchpad_launch_token({
// ... other params
websiteUrl: 'https://mytoken.com' // At least one required
})

Best Practices​

1. Always Calculate Before Trading​

Never skip the calculate step - it provides:

  • Accurate expectedAmount for slippage protection
  • Fee breakdown for transparency
  • Price impact analysis for informed decisions

2. Use Appropriate Limits​

Match your pageSize to the operation type:

  • Trades/User operations: Use 20 or less
  • Pools: Can use up to 100
  • Comments: Can use up to 50

3. Handle Slippage Appropriately​

Common slippage tolerance factors:

  • 0.01 (1%) - Low volatility, stable pools
  • 0.05 (5%) - Standard for most trades
  • 0.10 (10%) - High volatility, new tokens

4. Use Token Filtering Efficiently​

For single token lookups:

gala_launchpad_fetch_token_balance({
tokenName: 'anime',
address: 'eth|...'
})
// 99% payload reduction vs fetching all tokens

For discovery:

gala_launchpad_fetch_tokens_held({
search: 'dragon',
pageSize: 10
})

5. Verify Trades Complete​

After executing trades, always verify:

gala_launchpad_fetch_trades({
tokenName: 'woohoo',
userAddress: 'eth|...',
pageSize: 1,
sortOrder: 'DESC'
})

6. Check Availability Before Launch​

Always verify token name and symbol availability before launching:

// Step 1: Check name
gala_launchpad_check_token_name({ tokenName: 'mytoken' })

// Step 2: Check symbol
gala_launchpad_check_token_symbol({ symbol: 'MTK' })

// Step 3: Launch if both available
gala_launchpad_launch_token({ ... })

Quick Reference Card​

Trading Flow​

  1. calculate_buy_amount() or calculate_sell_amount()
  2. Extract result.amount from response
  3. Use result.amount as expectedAmount in buy/sell
  4. Verify with fetch_trades()

Lock/Unlock Flow​

  1. lock_tokens() - Lock tokens, passed as a tokens array (optional: lockAuthority, name, expires)
  2. unlock_tokens() - Release tokens, passed as a tokens array (must be lock authority)
  3. Use name to match specific locks when unlocking

Page Size Values (pageSize)​

  • Trades: 20 max
  • User ops: 20 max
  • Pools: 100 max

Type Parameter​

  • 'native' = GALA amount (most common)
  • 'token' = Exact token amount

Token Filtering​

  • tokenName = Exact match (faster)
  • search = Fuzzy match (discovery)

Address Format​

  • API expects: 'eth|abc123...'
  • Convert from: '0xabc123...'

For more details, see: