Skip to main content

🤖 Gala Launchpad SDK - AI Agent Integration Guide

Comprehensive guide for AI agents to understand, integrate, and build upon the Gala Launchpad SDK

SDK Version: 9.0.0 (launchpad-only; 343 public instance methods, counted from the LaunchpadSDK class body) MCP Server: @gala-chain/gala-mcp-server (tool catalog in its README; GALA_TOOLSETS=core,launchpad selects the launchpad tools) Target Audience: AI agents, MCP servers, automation tools, trading bots


📖 Table of Contents​

  1. Quick Start for AI Agents
  2. SDK Architecture Overview
  3. Complete Method Catalog
  4. Common AI Agent Workflows
  5. Type Reference for Code Generation
  6. Error Handling Patterns
  7. Best Practices for Agent Implementation
  8. Example MCP Tool Schemas
  9. Environment Configuration
  10. Testing and Validation

Quick Start for AI Agents​

Minimal Setup (3 Lines)​

import { AgentConfig } from '@gala-chain/launchpad-sdk';

const { sdk, validation } = await AgentConfig.quickSetup();
console.log(`Agent ready: ${validation?.ready}`);

What Just Happened?​

  1. Auto-detected environment from LAUNCHPAD_ENV or ENVIRONMENT (stage or prod), defaulting to prod
  2. Created or imported wallet from process.env.PRIVATE_KEY or generated new one
  3. Configured SDK with appropriate timeouts and debug settings
  4. Validated setup including balance checks and connectivity tests
  5. Ready for operations with full error context if something failed

quickSetup resolves to { sdk, wallet, config, validation? }: wallet is the AgentWallet (gala-core-sdk's generated wallet plus an ethers Wallet), config the resolved LaunchpadSDKConfig, and validation a SetupValidation that is present unless you pass autoValidate: false. It is { ready, sdk, wallet, issues: string[], warnings: string[], capabilities: { canTrade (balance >= 0.1 GALA), canCreateTokens (balance >= 100 GALA), hasBalance, connectionHealthy } }. AgentConfig.readOnlySetup() builds a wallet-less SDK, and multiWalletSetup(wallets, environment = 'stage') returns Record<string, LaunchpadSDK> with validation skipped.

Complete Setup with Options​

import { AgentConfig } from '@gala-chain/launchpad-sdk';

const { sdk, wallet, config, validation } = await AgentConfig.quickSetup({
environment: 'prod',
privateKey: process.env.TRADING_WALLET_KEY!,
timeout: 60000,
debug: false,
agentId: 'my-trading-bot-v1',
autoValidate: true
});

// Check capabilities before proceeding
if (validation === undefined || !validation.ready) {
console.error('Setup issues:', validation?.issues);
process.exit(1);
}

if (!validation.capabilities.canTrade) {
console.warn('Insufficient balance for trading:', validation.warnings);
}

// All good - start trading!
const pools = await sdk.fetchPools({ type: 'recent', pageSize: 10 });

Read-Only Mode Setup (No Wallet Required)​

For data analysis, monitoring, and query-only operations, you don't need a wallet configured. This reduces startup time and enables read-only agents without wallet secrets:

import { AgentConfig } from '@gala-chain/launchpad-sdk';

// Read-only mode: readOnlySetup builds an SDK with no wallet (it resolves to { sdk, config }).
// quickSetup without a privateKey does NOT do this: it falls back to PRIVATE_KEY or generates a wallet.
const { sdk } = await AgentConfig.readOnlySetup({
environment: 'prod',
timeout: 30000,
debug: false,
agentId: 'market-monitor-agent'
});

// All query operations work fine
const pools = await sdk.fetchPools({ type: 'recent', pageSize: 10 });
const price = await sdk.fetchTokenPrice({ tokenName: 'anime' });
const distribution = await sdk.fetchTokenDistribution('anime');

// ❌ This will throw ValidationError('WALLET_REQUIRED')
try {
await sdk.buy({
tokenName: 'anime',
amount: '1',
type: 'native',
expectedAmount: '100',
slippageToleranceFactor: 0.01
});
} catch (error) {
console.error('Cannot trade without wallet:', error instanceof Error ? error.message : error);
}

Read-Only vs Full-Access Comparison:

// ✅ READ-ONLY MODE (No wallet, no secrets needed)
const readOnly = await AgentConfig.readOnlySetup({
environment: 'prod',
agentId: 'data-analyzer'
// No wallet is created - safe for untrusted environments
});

// ✅ Available methods in read-only:
await readOnly.sdk.fetchPools({ type: 'recent' }); // ✅ Works
await readOnly.sdk.fetchPoolDetails('anime'); // ✅ Works
await readOnly.sdk.fetchTokenPrice({ tokenName: 'anime' }); // ✅ Works
await readOnly.sdk.fetchTokenDistribution('anime'); // ✅ Works
await readOnly.sdk.fetchGalaBalance('eth|...'); // ✅ Works
await readOnly.sdk.getComments({ tokenName: 'anime' }); // ✅ Works

// ❌ Operations requiring wallet:
await readOnly.sdk.buy(buyOptions); // ❌ Throws
await readOnly.sdk.sell(sellOptions); // ❌ Throws
await readOnly.sdk.transferGala(transferOptions); // ❌ Throws
await readOnly.sdk.createComment(commentOptions); // ❌ Throws

// ✅ FULL-ACCESS MODE (With wallet for signing operations)
const fullAccess = await AgentConfig.quickSetup({
environment: 'prod',
privateKey: process.env.PRIVATE_KEY!, // Now we have signing capability
agentId: 'trading-bot'
});

// ✅ Available methods in full-access:
await fullAccess.sdk.fetchPools({ type: 'recent' }); // ✅ Works
await fullAccess.sdk.buy(buyOptions); // ✅ Works
await fullAccess.sdk.transferGala(transferOptions); // ✅ Works
await fullAccess.sdk.createComment(commentOptions); // ✅ Works

Dynamic Wallet Configuration (Upgrade from Read-Only)​

You can start in read-only mode and upgrade to full-access dynamically when needed:

import { AgentConfig } from '@gala-chain/launchpad-sdk';
import { Wallet } from 'ethers';

// Start with read-only capability
const { sdk } = await AgentConfig.readOnlySetup({
environment: 'prod',
agentId: 'adaptive-agent'
// No wallet yet
});

// Check if wallet is available
console.log(`Has wallet: ${sdk.hasWallet()}`); // false

// Perform read-only operations
const pools = await sdk.fetchPools({ type: 'recent', pageSize: 10 });
console.log(`Found ${pools.items.length} pools`);

// Later, upgrade to full-access (e.g., triggered by user input or logic)
const shouldTrade = process.env.TRADING_WALLET_KEY !== undefined;
if (shouldTrade) {
sdk.setWallet(new Wallet(process.env.TRADING_WALLET_KEY!));
console.log(`Wallet configured: ${sdk.hasWallet()}`); // true

// Now trading operations work
const quote = await sdk.calculateBuyAmount({
tokenName: 'anime',
amount: '10',
type: 'native'
});

const result = await sdk.buy({
tokenName: 'anime',
amount: '10',
type: 'native',
expectedAmount: quote.amount,
slippageToleranceFactor: 0.01
});

console.log(`Trade executed: ${result.transactionId}`);
}

sdk.cleanup();

Key Points:

  • ✅ Start Simple: Initialize without wallet for read-only operations
  • ✅ Flexible: Add wallet later with setWallet() when needed
  • ✅ Type-Safe: validateWallet() checks before signing operations
  • ✅ No Secrets: Read-only agents don't expose private keys
  • ✅ Progressive Enhancement: Begin with queries, add trading capability later

SDK Architecture Overview​

Service-Based Backend Alignment​

The SDK internally uses 5 backend-aligned services (you don't interact with these directly):

  1. LaunchpadService → https://lpad-backend-{env}.defi.gala.com

    • Pool management, trade history, comments, profiles
  2. GalaChainService → https://galachain-gateway-{env}.galachain.com

    • Balances, transfers, blockchain operations
  3. Swap backend (dexBackendBaseUrl) → the stage preset, prod https://dex-backend-prod1.defi.gala.com

    • Read-only: LaunchpadPriceService reads GET /market/price for the USD price of a launchpad token (fetchTokenPrice). DEX quotes, pools, positions and market data are gswap-sdk's, not this SDK's
  4. BundleService → https://bundle-backend-{env}.defi.gala.com

    • Token trading, transaction bundling
  5. WebSocketService → wss://bundle-backend-{env}.defi.gala.com

    • Real-time transaction monitoring

Flattened Public API​

You interact with a single SDK instance that exposes most methods directly, with one namespaced exception for DEX trading:

// No child controllers for launchpad/chain operations - everything on sdk.*
sdk.fetchPools(...) // Pool operations
sdk.buy(...) // Trading operations
sdk.fetchGalaBalance(...) // Balance queries
sdk.createComment(...) // Social features
sdk.transferGala(...) // Token transfers

// GSwap DEX trading is gswap-sdk's own client (launchpad-sdk has none):
// const gSwap = new GSwap({ env, signer: new PrivateKeySigner(key), walletAddress: sdk.getAddress() });
gSwap.pools.getPools(...) // Pool discovery
gSwap.quoting.quoteExactInput(...) // Swap quotes
gSwap.swaps.swap(...) // Queued swap submission

This flattened design simplifies agent implementation for launchpad/chain operations - no need to navigate controller hierarchies. DEX trading, quoting, positions, symbols, assets, market data and the trading competition live in @gala-chain/gswap-sdk's GSwap client (gSwap.*), which you build with the same key.


Complete Method Catalog​

Note: This section covers a core subset of methods across eight categories. The LaunchpadSDK class has 343 public instance methods (plus the events and realtime getters and the static cleanupAll), counted from the class body of the built dist/LaunchpadSDK.d.ts: every method declared in the class that is not private/protected/static. They also cover bridging, streaming, chat, session auth and more. GSwap DEX trading is gswap-sdk's GSwap client (gSwap.*), not part of this SDK. See the API Reference for the complete list.

Category 1: Pool Management​

fetchPools(options?): Promise<PoolsResult>​

Fetch token pools with filtering and pagination.

Options:

{
type?: 'recent' | 'popular' | 'recordings' | 'seconds_streamed',
tokenName?: string, // Exact match
search?: string, // Fuzzy search
hasUpcomingShows?: boolean,
language?: string,
recentlyStreamed?: number,
hasRecordings?: boolean,
streamStatus?: 'idle' | 'active' | 'disabled',
isGraduated?: boolean, // true = graduated, false = still on the curve (both sent)
creatorAddress?: string, // 'eth|<40 hex>' or 'client|<24 hex>'
cursor?: string, // Omit for the first page
pageSize?: number // Cursor-based pagination
}

Returns (ListResult<PoolData>):

{
items: PoolData[],
pageInfo: {
hasNextPage: boolean,
endCursor?: string | null,
hasPreviousPage?: boolean,
startCursor?: string | null,
totalCount?: number // fetchAll... results only
}
}

PoolData carries id, tokenName, symbol, description, amount, creatorAddress, vaultAddress, createdAt (string), image, the social URLs, and optional reverse bonding curve fee fields.

Usage:

const recent = await sdk.fetchPools({ type: 'recent', pageSize: 10 });
console.log(`Got ${recent.items.length} pools, more: ${recent.pageInfo.hasNextPage}`);

for (const pool of recent.items) {
console.log(`${pool.tokenName}: ${pool.symbol}`);
}

fetchPoolDetails(tokenName: string): Promise<PoolDetailsData>​

Get detailed pool state directly from GalaChain bonding curve contract.

Returns:

{
basePrice: string,
euler: string,
exponentFactor: string,
maxSupply: string,
nativeToken: TokenInfo, // GALA
nativeTokenQuantity: string, // GALA in the vault
sellingToken: TokenInfo,
sellingTokenQuantity: string,
currentSupply?: string, // maxSupply - sellingTokenQuantity
saleOwner: string,
saleStatus: string, // e.g. 'ACTIVE', 'PENDING', 'COMPLETED'
saleStartTime?: number, // Unix seconds
isGraduated: boolean, // saleStatus === 'Completed'
vaultAddress: string,
reverseBondingCurveMinFeePortion: string,
reverseBondingCurveMaxFeePortion: string,
reverseBondingCurveConfiguration?: { minFeePortion: string, maxFeePortion: string },
hasReverseBondingCurveFee: boolean,
reverseBondingCurveMinFeeFactor?: number,
reverseBondingCurveMaxFeeFactor?: number,
reverseBondingCurveNetFeeFactor?: number
}

Usage:

const details = await sdk.fetchPoolDetails('dragnrkti');
console.log(`Sale status: ${details.saleStatus}, graduated: ${details.isGraduated}`);
console.log(`Current supply: ${details.currentSupply} / ${details.maxSupply}`);
console.log(`GALA in vault: ${details.nativeTokenQuantity}`);

fetchTokenDistribution(tokenName: string): Promise<TokenDistributionResult>​

Get holder distribution and supply metrics.

Returns:

{
holders: Array<{
address: string,
balance: string, // Decimal string
percentage: number // 0-100 of total supply
}>,
totalSupply: string,
totalHolders: number,
lastUpdated: Date
}

fetchVolumeData(options): Promise<GraphDataResult>​

Get time-series graph data points for charting.

Options (FetchVolumeDataOptions):

{
tokenName: string,
from?: number, // Start timestamp
to?: number, // End timestamp
resolution?: number // Resolution in seconds
}

Returns (GraphDataResult):

{
dataPoints: Array<{
timestamp: number,
value: number,
[key: string]: unknown // Additional metrics
}>
}

isTokenNameAvailable(tokenName: string): Promise<boolean>​

Check if token name is available for creation.

Usage:

const available = await sdk.isTokenNameAvailable('mynewtoken');
if (!available) {
console.log('Name already taken');
}

isTokenSymbolAvailable(symbol: string): Promise<boolean>​

Check if token symbol is available for creation.

resolveVaultAddress(tokenName: string): Promise<string>​

Get the GalaChain vault address for a token (needed for some operations).

Returns: Promise<string | null>, a vault address of the form "service|Token$Unit$SYMBOL$eth:address$launchpad", or null when none resolves.


Category 2: Trading Operations​

calculateBuyAmount(options): Promise<AmountCalculationResult>​

Calculate how many tokens you'll receive for a given GALA amount (or vice versa).

Options:

{
tokenName: string,
amount: string, // Standard decimal format (e.g., "1", "10.5")
type: 'native' | 'exact' // 'native' = spending GALA, 'exact' = buying exact tokens
}

Returns:

{
amount: string, // Calculated amount (opposite of input type)
transactionFee: string, // Platform fee in GALA
reverseBondingCurveFee: string, // RBC fee in GALA
gasFee: string // Gas fee (fixed at 1 GALA)
}

There is no price-impact field; derive one from amount and the input amount if you need it.

Units: amount and every returned amount are decimal strings in whole units: GALA for 'native', tokens for 'exact' ('10' is 10 GALA, '1000' is 1000 tokens). They are never base units or wei.

Usage:

// How many tokens for 10 GALA?
const quote = await sdk.calculateBuyAmount({
tokenName: 'dragnrkti',
amount: '10', // 10 GALA
type: 'native'
});

console.log(`You'll receive: ${quote.amount} DRAGNRKTI tokens`);
console.log(`Transaction fee: ${quote.transactionFee} GALA`);

calculateSellAmount(options): Promise<AmountCalculationResult>​

Calculate how much GALA you'll receive for selling tokens (or how many tokens needed for target GALA).

Same interface as calculateBuyAmount

buy(options): Promise<TradeResult>​

Execute a token purchase via GalaChain. amount and expectedAmount are decimal strings in whole GALA (type: 'native') or whole tokens (type: 'exact'), never base units.

Options:

{
tokenName: string,
amount: string,
type: 'native' | 'exact',
expectedAmount: string, // From calculateBuyAmount - REQUIRED
slippageToleranceFactor?: number, // Decimal format (0.05 = 5%) - optional
maxAcceptableReverseBondingCurveFee?: string,
maxAcceptableReverseBondingCurveFeeSlippageFactor?: number,
privateKey?: string // Optional per-call key override
}

Returns (TradeResult, confirmed over the bundler socket):

{
transactionId: string,
blockHash?: string,
gasUsed?: string,
timestamp: number, // Confirmation time, number not Date
type: 'buy' | 'sell',
method: 'native' | 'exact',
inputAmount: string, // GALA for buys, tokens for sells
outputAmount: string, // Tokens for buys, GALA for sells
totalFees: string,
tokenName: string,
vaultAddress: string,
slippageTolerance?: number
}

Usage:

// Step 1: Get quote
const quote = await sdk.calculateBuyAmount({
tokenName: 'dragnrkti',
amount: '5', // 5 GALA
type: 'native'
});

// Step 2: Execute trade with slippage protection
const result = await sdk.buy({
tokenName: 'dragnrkti',
amount: '5', // 5 GALA, same unit as the quote
type: 'native',
expectedAmount: quote.amount, // REQUIRED
slippageToleranceFactor: 0.05 // 5% slippage
});

console.log(`Transaction ID: ${result.transactionId}`);
console.log(`Spent ${result.inputAmount} GALA, received ${result.outputAmount} tokens`);

sell(options): Promise<TradeResult>​

Execute a token sale via GalaChain.

Same interface as buy() (SellTokenOptions; type: 'exact' | 'native').

fetchTrades(options): Promise<TradesResult>​

Get trade history with filtering.

Options:

{
tokenName: string, // Required
tradeType?: 'buy' | 'sell',
userAddress?: string,
cursor?: string,
pageSize?: number,
startDate?: Date,
endDate?: Date,
sortOrder?: 'asc' | 'desc'
}

Returns (ListResult<TradeInfo>):

{
items: Array<{
id: string,
userAddress: string,
tradeType: 'buy' | 'sell',
tokenAmount: string,
vaultAddress: string,
createdAt: string,
updatedAt: string,
slippageTolerance?: string,
deadline?: number,
[key: string]: unknown // Additional trade metadata
}>,
pageInfo: { hasNextPage, endCursor?, hasPreviousPage?, startCursor?, totalCount? }
}

Category 3: Balance & Portfolio​

fetchGalaBalance(address?: string): Promise<TokenBalanceResult | null>​

Get GALA balance for a wallet (defaults to SDK wallet). Resolves to null when no balance is returned.

Returns (TokenBalanceResult):

{
quantity: string, // Decimal string in whole GALA (e.g., "100.5")
collection: string, // "GALA"
category: string, // "Unit"
tokenId: string, // "GALA|Unit|none|none"
inUseHolds?: GalaChainTokenHold[],
lockedHolds?: GalaChainTokenHold[],
lockedQuantity?: string,
inUseQuantity?: string,
availableQuantity?: string // quantity - lockedQuantity - inUseQuantity
}

Usage:

const balance = await sdk.fetchGalaBalance();
console.log(`Balance: ${balance?.quantity ?? '0'} GALA`);
console.log(`Available: ${balance?.availableQuantity}`);

fetchTokenBalance(options): Promise<TokenBalanceResult | null>​

Get a token balance for a wallet. Same result shape as fetchGalaBalance.

Options (FetchTokenBalanceOptions):

{
address: string, // Required: eth|... or 0x...
tokenName?: string, // For launchpad tokens
tokenId?: TokenId, // string, TokenClassKey or TokenInstanceKey
withExpired?: boolean // Include expired holds (default: false)
}

fetchTokensHeld(options): Promise<UserTokenListResult>​

Get all tokens held by a wallet.

Options:

{
address?: string, // Defaults to the SDK wallet
tokenName?: string, // Exact match
search?: string, // Fuzzy search
cursor?: string,
pageSize?: number
}

Returns (UserTokenListResult):

{
tokens: Array<{
id: string, name: string, symbol: string, type: UserTokenType,
address: string, balance: string, decimals: number,
metadata?: { description?: string, image?: string },
createdAt: string, updatedAt: string
}>,
pageInfo: PageInfo,
total?: number
}

fetchTokensCreated(options): Promise<UserTokenListResult>​

Get all tokens created by a wallet. Same options and result as fetchTokensHeld.

fetchProfile(address?: string): Promise<PublicUserProfile>​

Get the public profile of an address (defaults to the SDK wallet): fullName, profileImage and bio (each nullable), stats (tokensCreated, tokensGraduated, graduationRate, totalTrades, totalVolumeGala, ...), the four badge ladders (launchBadge, successBadge, volumeBadge, engagementBadge, each a BadgeStatus[]), isLiveStreaming and liveStreamToken. An address with no profile row still answers a profile (the name, image and bio are null).


Category 4: Token Creation​

launchToken(data): Promise<TokenLaunchResult>​

Create a new token on the launchpad. The supply and bonding curve are fixed by the launchpad; you provide identity, optional pre-buy and optional reverse bonding curve fees.

Data (LaunchTokenData):

{
tokenName: string, // Lowercase, alphanumeric, max 10 chars
tokenSymbol: string, // 3-10 chars
tokenDescription: string, // Max 500 chars
tokenImage?: File | Buffer | string, // File, Buffer or URL string
preBuyQuantity?: string, // Whole GALA decimal string, default "0"
websiteUrl?: string,
telegramUrl?: string,
twitterUrl?: string,
instagramUrl?: string,
facebookUrl?: string,
redditUrl?: string,
tiktokUrl?: string,
reverseBondingCurveConfiguration?: { // Default { minFeePortion: "0.1", maxFeePortion: "0.5" }
minFeePortion: string,
maxFeePortion: string
},
saleStartTime?: number, // Future Unix timestamp in seconds; omit to start immediately
privateKey?: string
}

Returns (TokenLaunchResult):

{
transactionId: string,
blockHash?: string,
gasUsed?: string,
timestamp: number,
vaultAddress: string,
tokenStringKey: string, // Token$Unit$SYMBOL$...
tokenName: string,
tokenSymbol: string,
creatorAddress: string, // eth|...
tokenImage?: string,
preBuyQuantity?: string
}

Usage:

const result = await sdk.launchToken({
tokenName: 'mynewtoken',
tokenSymbol: 'MNT',
tokenDescription: 'My amazing token',
tokenImage: 'https://example.com/image.png',
preBuyQuantity: '100', // 100 GALA
reverseBondingCurveConfiguration: { minFeePortion: '0.1', maxFeePortion: '0.5' }
});

console.log(`Token created: ${result.transactionId} (${result.vaultAddress})`);

uploadTokenImage(options: UploadImageByTokenNameOptions): Promise<string>​

Upload a token image; resolves to the uploaded image URL. Requires a login session, not a wallet.

Options:

{
tokenName: string,
options: {
file: File | Buffer // Browser File or Node.js Buffer
},
privateKey?: string // Optional per-call key override ('0x' + 64 hex)
}

updateProfile(data: UpdateProfileData): Promise<void>​

Update user profile. data is { profileImage: string, fullName: string, address: string, privateKey?: string }.


Category 5: Comments & Social​

createComment(options: CreateCommentOptions): Promise<CreateCommentResult>​

Post a comment on a token pool. Requires a wallet / JWT.

Options:

{
tokenName: string,
content: string // Max 2000 chars
}

Returns:

{
comment: WrittenComment // The created comment: numeric id, messageId, content, userAddress, createdAt, updatedAt (no tokenName)
}

Related: updateComment(id, { content }), deleteComment(id), addReactionToComment(...), removeReactionFromComment(...).

getComments(options: GetCommentsOptions): Promise<CommentsResult>​

Get comments for a token pool, or by user. At least one of tokenName or userAddress is required.

Options:

{
tokenName?: string,
userAddress?: string, // eth|... or 0x...
cursor?: string, // Omit for the first page
pageSize?: number // Default: 20, max: 50
}

Returns:

{
messages: Message[], // id = messageId (string), user, reactions: { counts, userReacted? }
pageInfo: PageInfo
}

Category 6: Token Transfers​

transferGala(data: TransferGalaData): Promise<GalaChainTransferReceipt>​

Transfer GALA tokens to another wallet via GalaChain.

Options:

{
recipientAddress: string, // Supports 0x... or eth|... format
amount: string, // Decimal string in whole GALA (e.g. "0.001", "1.5")
uniqueKey?: string, // Optional idempotency key, auto-generated when omitted
privateKey?: string // Optional per-call key override
}

Returns (GalaChainTransferReceipt): { transactionId: string, blockNumber?: number }

Usage:

const result = await sdk.transferGala({
recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
amount: '1', // 1 GALA
uniqueKey: 'galaconnect-operation-my-transfer-123'
});

console.log(`Transfer ID: ${result.transactionId}`);

transferToken(data: TransferTokenData): Promise<GalaChainTransferReceipt>​

Transfer launchpad tokens to another wallet via GalaChain.

Options:

{
to: string, // eth|... or 0x...
tokenName?: string, // Or tokenId
tokenId?: TokenId,
amount: string, // Decimal string in whole tokens
uniqueKey?: string,
privateKey?: string
}

Returns: { transactionId: string, blockNumber?: number }


Category 7: Token Lock/Unlock​

lockTokens(data: LockTokensData): Promise<LockTokensResult>​

Lock one or more tokens on GalaChain for staking, escrow, or vesting purposes. The batch is a single transaction (all tokens lock or none do); lock parameters (lockAuthority, expires, name) from the first entry that sets them apply to the whole batch.

Options:

{
tokens: Array<{
tokenName?: string, // Token to lock (e.g., 'anime'), used when tokenId is absent
tokenId?: TokenId, // Or a token id / class key / instance key
amount: string, // Amount to lock (standard decimal format)
lockAuthority?: string, // Address that can unlock (defaults to caller)
expires?: number, // Optional expiration timestamp in milliseconds
name?: string // Optional lock name for matching during unlock
}>,
uniqueKey?: string, // Optional idempotency key (auto-generated)
privateKey?: string // Optional per-call key override
}

Returns:

{
transactionId?: string,
blockNumber?: number,
locked: Array<{ tokenClassKey, quantity: string, lockAuthority: string }>
}

Usage:

// Basic lock (caller becomes lock authority)
const result = await sdk.lockTokens({
tokens: [{ tokenName: 'anime', amount: '1000' }] // Lock 1000 tokens
});
console.log(`Lock transaction: ${result.transactionId}`);

// Lock with custom authority (escrow pattern)
const escrowResult = await sdk.lockTokens({
tokens: [{
tokenName: 'anime',
amount: '500',
lockAuthority: 'eth|1234567890abcdef...', // Third party can unlock
name: 'escrow-order-001'
}]
});

// Time-locked (auto-releases after expiration)
const timedResult = await sdk.lockTokens({
tokens: [{
tokenName: 'anime',
amount: '200',
expires: Date.now() + (30 * 24 * 60 * 60 * 1000), // 30 days
name: 'vesting-cliff-1'
}]
});

unlockTokens(data: UnlockTokensData): Promise<UnlockTokensResult>​

Unlock previously locked tokens on GalaChain (batch, single transaction). Must be signed by the lock authority.

Options:

{
tokens: Array<{
tokenName?: string, // Token to unlock
tokenId?: TokenId,
amount: string, // Amount to unlock
name?: string // Optional lock name to match specific lock
}>,
uniqueKey?: string,
privateKey?: string
}

Returns: { transactionId?: string, blockNumber?: number, unlocked: Array<{ tokenClassKey, quantity }> }

Usage:

// Basic unlock
const result = await sdk.unlockTokens({
tokens: [{ tokenName: 'anime', amount: '500' }]
});
console.log(`Unlock transaction: ${result.transactionId}`);

// Unlock specific named lock
const namedResult = await sdk.unlockTokens({
tokens: [{
tokenName: 'anime',
amount: '500',
name: 'escrow-order-001' // Match the lock by name
}]
});

Lock/Unlock Patterns:

// Pattern 1: Self-staking (user locks their own tokens)
await sdk.lockTokens({ tokens: [{ tokenName: 'anime', amount: '1000' }] });
// Later...
await sdk.unlockTokens({ tokens: [{ tokenName: 'anime', amount: '1000' }] });

// Pattern 2: Escrow (third party authority)
await sdk.lockTokens({
tokens: [{
tokenName: 'anime',
amount: '500',
lockAuthority: 'eth|EscrowContract...', // Escrow contract unlocks
name: 'trade-12345'
}]
});

// Pattern 3: Vesting schedule
await sdk.lockTokens({
tokens: [{
tokenName: 'anime',
amount: '10000',
expires: Date.now() + (365 * 24 * 60 * 60 * 1000), // 1 year cliff
name: 'employee-vesting-2025'
}]
});

Category 8: Utilities​

getAddress(): string​

Get the SDK wallet address in backend format (eth|...).

getEthereumAddress(): string​

Get the SDK wallet address in Ethereum format (0x...).

cleanup(): void​

Cleanup resources (close WebSocket connections, clear timers).

Always call this before exiting your agent!

process.on('SIGINT', () => {
sdk.cleanup();
process.exit(0);
});

Common AI Agent Workflows​

Workflow 1: Trading Bot​

import { AgentConfig } from '@gala-chain/launchpad-sdk';

// Setup
const { sdk } = await AgentConfig.quickSetup({
environment: 'prod',
agentId: 'trading-bot',
autoValidate: true
});

// Monitor pools for opportunities
const pools = await sdk.fetchPools({ type: 'popular', pageSize: 50 });

for (const pool of pools.items) {
// Get current price
const quote = await sdk.calculateBuyAmount({
tokenName: pool.tokenName,
amount: '1', // 1 GALA
type: 'native'
});

// The quote carries amount and fees (no price-impact field): apply your own threshold
const minTokensPerGala = 1000;
if (Number(quote.amount) >= minTokensPerGala) {
console.log(`Good opportunity: ${pool.tokenName}`);

// Execute trade
const result = await sdk.buy({
tokenName: pool.tokenName,
amount: '1',
type: 'native',
expectedAmount: quote.amount,
slippageToleranceFactor: 0.05
});

console.log(`Bought: ${result.transactionId}`);
}
}

// Cleanup
sdk.cleanup();

Workflow 2: Portfolio Monitor​

import { AgentConfig } from '@gala-chain/launchpad-sdk';

const { sdk } = await AgentConfig.quickSetup();

// Check GALA balance
const galaBalance = await sdk.fetchGalaBalance();
console.log(`GALA: ${galaBalance?.quantity ?? '0'}`);

// Get held tokens (first page of 100; follow pageInfo.endCursor for more)
const held = await sdk.fetchTokensHeld({
address: sdk.getAddress(),
pageSize: 100
});

console.log(`Holding ${held.tokens.length} tokens:`);

for (const token of held.tokens) {
console.log(`${token.name} (${token.symbol}): ${token.balance} tokens`);
}

sdk.cleanup();

Workflow 3: Token Creator Agent​

import { AgentConfig } from '@gala-chain/launchpad-sdk';

const { sdk, validation } = await AgentConfig.quickSetup();

// Check if we have enough GALA
if (!validation?.capabilities.canCreateTokens) {
console.error('Need at least 100 GALA to create tokens');
process.exit(1);
}

// Check name availability
const available = await sdk.isTokenNameAvailable('mytoken');
if (!available) {
console.error('Name already taken');
process.exit(1);
}

// Upload image first
import { readFile } from 'node:fs/promises';

const imageUrl = await sdk.uploadTokenImage({
tokenName: 'mytoken',
options: { file: await readFile('/path/to/image.png') }
});

// Create token
const result = await sdk.launchToken({
tokenName: 'mytoken',
tokenSymbol: 'MTK',
tokenDescription: 'Agent-created token',
tokenImage: imageUrl,
preBuyQuantity: '0'
});

console.log(`Token created: ${result.transactionId}`);
sdk.cleanup();

Workflow 4: Multi-Wallet Management​

import { AgentConfig } from '@gala-chain/launchpad-sdk';

// Setup multiple wallets for different purposes
const sdks = await AgentConfig.multiWalletSetup({
trader: process.env.TRADER_WALLET!,
creator: process.env.CREATOR_WALLET!,
monitor: 'generate' // Read-only operations
}, 'prod');

const { trader, creator, monitor } = sdks;
if (trader === undefined || creator === undefined || monitor === undefined) throw new Error('wallet setup failed');

// Use trader wallet for trading
const tradeQuote = await trader.calculateBuyAmount({
tokenName: 'dragnrkti',
amount: '5', // 5 GALA
type: 'native'
});
const tradeResult = await trader.buy({
tokenName: 'dragnrkti',
amount: '5',
type: 'native',
expectedAmount: tradeQuote.amount,
slippageToleranceFactor: 0.05
});

// Use creator wallet for token creation
const createResult = await creator.launchToken({
tokenName: 'newtoken',
tokenSymbol: 'NEW',
tokenDescription: 'A new token'
});

// Use monitor wallet for read-only operations (no balance needed)
const pools = await monitor.fetchPools({ type: 'recent' });

// Cleanup all
Object.values(sdks).forEach(sdk => sdk.cleanup());

Workflow 5: Token Locking Agent​

import { AgentConfig } from '@gala-chain/launchpad-sdk';

const { sdk } = await AgentConfig.quickSetup({
environment: 'prod',
agentId: 'staking-agent'
});

// Staking flow - lock tokens for rewards
async function stakeTokens(tokenName: string, amount: string) {
// Lock tokens (user is the lock authority by default)
const lockResult = await sdk.lockTokens({
tokens: [{
tokenName,
amount,
name: `stake-${Date.now()}` // Track stake ID
}]
});

console.log(`Staked ${amount} ${tokenName}: ${lockResult.transactionId}`);
return lockResult;
}

// Escrow flow - third party releases funds
async function createEscrow(
tokenName: string,
amount: string,
escrowAuthority: string,
orderId: string
) {
const lockResult = await sdk.lockTokens({
tokens: [{
tokenName,
amount,
lockAuthority: escrowAuthority, // Escrow contract/service unlocks
name: `escrow-${orderId}`
}]
});

console.log(`Created escrow for order ${orderId}: ${lockResult.transactionId}`);
return lockResult;
}

// Vesting flow - time-locked tokens
async function createVestingSchedule(
tokenName: string,
amount: string,
vestingPeriodDays: number
) {
const expiresAt = Date.now() + (vestingPeriodDays * 24 * 60 * 60 * 1000);

const lockResult = await sdk.lockTokens({
tokens: [{
tokenName,
amount,
expires: expiresAt,
name: `vesting-${Date.now()}`
}]
});

console.log(`Created ${vestingPeriodDays}-day vesting: ${lockResult.transactionId}`);
return lockResult;
}

// Unlock tokens (must be lock authority)
async function unstake(tokenName: string, amount: string, stakeName?: string) {
const unlockResult = await sdk.unlockTokens({
tokens: [{
tokenName,
amount,
...(stakeName === undefined ? {} : { name: stakeName }) // Match specific lock if named
}]
});

console.log(`Unstaked ${amount} ${tokenName}: ${unlockResult.transactionId}`);
return unlockResult;
}

// Execute staking workflow
await stakeTokens('anime', '1000');
// ... time passes, rewards accrue ...
await unstake('anime', '1000');

sdk.cleanup();

Type Reference for Code Generation​

Key Types to Know​

// Pool data structure (abridged; see src/types/launchpad.dto.ts)
interface PoolData {
id: string;
tokenName: string;
symbol: string;
description: string;
amount: string;
creatorAddress: string;
vaultAddress: string;
createdAt: string;
image: string;
// ...social URLs, optional reverse bonding curve fee fields
}

// Cursor-paginated list results (PoolsResult = ListResult<PoolData>, TradesResult = ListResult<TradeInfo>)
interface ListResult<T> {
items: T[];
pageInfo: PageInfo;
}

interface PageInfo {
hasNextPage: boolean;
endCursor?: string | null; // the next request's cursor; null on the last page
hasPreviousPage?: boolean;
startCursor?: string | null;
totalCount?: number; // fetchAll... results only (the backend sends none)
}

// Amount calculation results (decimal strings in whole GALA / whole tokens)
interface AmountCalculationResult {
amount: string;
transactionFee: string;
reverseBondingCurveFee: string;
gasFee: string;
}

// Confirmed trade result (buy and sell)
interface TradeResult {
transactionId: string;
blockHash?: string;
gasUsed?: string;
timestamp: number;
type: 'buy' | 'sell';
method: 'native' | 'exact';
inputAmount: string;
outputAmount: string;
totalFees: string;
tokenName: string;
vaultAddress: string;
slippageTolerance?: number;
}

// Transfer receipt (transferGala, transferToken)
interface GalaChainTransferReceipt {
transactionId: string;
blockNumber?: number;
}

// Balance info (fetchGalaBalance, fetchTokenBalance; both may resolve to null)
interface TokenBalanceResult {
quantity: string;
collection: string;
category: string;
tokenId: string;
lockedQuantity?: string;
inUseQuantity?: string;
availableQuantity?: string;
// ...inUseHolds / lockedHolds
}

// Options patterns (cursor-based pagination everywhere)
interface FetchPoolsOptions {
type?: 'recent' | 'popular' | 'recordings' | 'seconds_streamed';
tokenName?: string;
search?: string;
cursor?: string;
pageSize?: number;
// ...hasUpcomingShows, language, recentlyStreamed, hasRecordings, streamStatus, isGraduated, creatorAddress
}

interface BuyTokenOptions {
tokenName: string;
amount: string;
type: 'native' | 'exact';
expectedAmount: string;
slippageToleranceFactor?: number;
}

// Lock/Unlock options (Category 7)
interface LockTokenEntry {
tokenName?: string; // Token to lock (or tokenId)
tokenId?: TokenId;
amount: string; // Amount in standard decimal format
lockAuthority?: string; // Address that can unlock (defaults to caller)
expires?: number; // Optional expiration timestamp in ms
name?: string; // Optional lock name for matching
}

interface LockTokensData {
tokens: LockTokenEntry[];
uniqueKey?: string;
privateKey?: string;
}

interface UnlockTokenEntry {
tokenName?: string; // Token to unlock (or tokenId)
tokenId?: TokenId;
amount: string; // Amount to unlock
name?: string; // Optional lock name to match
}

interface UnlockTokensData {
tokens: UnlockTokenEntry[];
uniqueKey?: string;
privateKey?: string;
}

// Error types
class ValidationError extends Error {
field?: string;
code?: string;
}

class TransactionFailedError extends Error {
readonly transactionId: string;
readonly status: string;
}

Error Handling Patterns​

Validation Errors​

import { ValidationError } from '@gala-chain/launchpad-sdk';

try {
await sdk.buy({
tokenName: 'invalid!name', // Invalid characters
amount: 'not-a-number', // Invalid format
type: 'native',
expectedAmount: '...',
slippageToleranceFactor: 0.05
});
} catch (error) {
if (error instanceof ValidationError) {
console.error(`Validation failed: ${error.field} - ${error.code}`);
// Handle validation error
}
}

Transaction Errors​

import { TransactionFailedError } from '@gala-chain/launchpad-sdk';

try {
const result = await sdk.buy({ tokenName: 'anime', amount: '100', type: 'native', expectedAmount: '1' });
console.log(`Success: ${result.transactionId}`);
} catch (error) {
if (error instanceof TransactionFailedError) {
console.error(`Transaction ${error.transactionId} failed: ${error.status}`);
// Handle transaction failure
}
}

Network Errors​

try {
const pools = await sdk.fetchPools({ type: 'recent' });
} catch (error) {
const code = (error as { code?: string }).code;
if (code === 'ECONNREFUSED') {
console.error('Backend unreachable');
} else if (code === 'ETIMEDOUT') {
console.error('Request timeout');
} else {
console.error('Unknown error:', error);
}
}

Setup Validation​

const { sdk, validation } = await AgentConfig.quickSetup();

if (validation === undefined || !validation.ready) {
console.error('Setup failed:');
validation?.issues.forEach(issue => console.error(`- ${issue}`));
process.exit(1);
}

if (validation.warnings.length > 0) {
console.warn('Setup warnings:');
validation.warnings.forEach(warn => console.warn(`- ${warn}`));
}

Best Practices for Agent Implementation​

1. Always Use AgentConfig​

// ❌ Bad - manual setup
import { LaunchpadSDK } from '@gala-chain/launchpad-sdk';
import { Wallet } from 'ethers';
const wallet = new Wallet(process.env.PRIVATE_KEY!);
const manualSdk = new LaunchpadSDK({ wallet, baseUrl: 'https://lpad-backend-prod1.defi.gala.com' });

// ✅ Good - AgentConfig handles everything
import { AgentConfig } from '@gala-chain/launchpad-sdk';
const { sdk } = await AgentConfig.quickSetup();

2. Validate Before Operating​

const { sdk, validation } = await AgentConfig.quickSetup({
autoValidate: true
});

// Check specific capabilities
if (!validation?.capabilities.canTrade) {
console.error('Insufficient balance for trading');
process.exit(1);
}

3. Always Calculate Before Trading​

async function tradeCarefully(): Promise<void> {
// ❌ Bad - trading blindly
await sdk.buy({
tokenName: 'dragnrkti',
amount: '5',
type: 'native',
expectedAmount: '???', // What should this be?
slippageToleranceFactor: 0.05
});

// ✅ Good - calculate first
const quote = await sdk.calculateBuyAmount({
tokenName: 'dragnrkti',
amount: '5', // 5 GALA
type: 'native'
});

// Check quote before executing: the quote has amount and fees, no price-impact field
const totalFeesGala = Number(quote.transactionFee) + Number(quote.reverseBondingCurveFee) + Number(quote.gasFee);
if (totalFeesGala > 0.1 * 5) {
console.warn('Fees exceed 10% of the trade, skipping');
return;
}

await sdk.buy({
tokenName: 'dragnrkti',
amount: '5',
type: 'native',
expectedAmount: quote.amount,
slippageToleranceFactor: 0.05
});
}

4. Use Slippage Protection​

// ❌ Bad - no slippage protection
slippageToleranceFactor: 0 // Will fail if price moves

// ✅ Good - reasonable slippage
slippageToleranceFactor: 0.05 // 5% tolerance for normal volatility
slippageToleranceFactor: 0.10 // 10% for high volatility

// ✅ Good - choose per trade size
const slippage = Number(amount) < 100 ? 0.02 : 0.05;

5. Handle Rate Limits​

// Implement exponential backoff for rate limits
async function retryWithBackoff<T>(
fn: () => Promise<T>,
maxRetries = 3,
baseDelay = 1000
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if ((error as { response?: { status?: number } }).response?.status === 429) { // Rate limited
const delay = baseDelay * Math.pow(2, i);
console.log(`Rate limited, retrying in ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
throw new Error('Max retries exceeded');
}

// Usage
const pools = await retryWithBackoff(() =>
sdk.fetchPools({ type: 'recent' })
);

6. Clean Up Resources​

// Always cleanup before exiting
process.on('SIGINT', () => {
console.log('Shutting down agent...');
sdk.cleanup();
process.exit(0);
});

process.on('SIGTERM', () => {
sdk.cleanup();
process.exit(0);
});

// Or use try/finally
try {
// Agent operations
await sdk.fetchPools({ type: 'recent' });
} finally {
sdk.cleanup();
}

7. Environment-Specific Configuration​

// Stage - longer timeouts, debug enabled
const { sdk: devSdk } = await AgentConfig.quickSetup({
environment: 'stage',
timeout: 60000,
debug: true
});

// Production - optimized settings
const { sdk: prodSdk } = await AgentConfig.quickSetup({
environment: 'prod',
timeout: 30000,
debug: false,
agentId: 'production-bot-v1'
});

8. Secure Wallet Management​

// ❌ Bad - hardcoded keys
const { sdk: hardcoded } = await AgentConfig.quickSetup({
privateKey: '0x1234567890abcdef...'
});

// ✅ Good - environment variables
const { sdk: fromEnv } = await AgentConfig.quickSetup({
privateKey: process.env.PRIVATE_KEY! // From .env file
});

// ✅ Good - multi-wallet with different permissions
const sdks = await AgentConfig.multiWalletSetup({
trading: process.env.TRADING_WALLET!, // Low balance, frequent use
creation: process.env.CREATION_WALLET!, // High balance, rare use
monitoring: 'generate' // No balance needed
}, 'prod');

Example MCP Tool Schemas​

Tool 1: Fetch Pools​

{
"name": "gala_launchpad_fetch_pools",
"description": "Fetch token pools from Gala Launchpad with filtering and pagination",
"inputSchema": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["recent", "popular", "recordings", "seconds_streamed"],
"description": "Type of pools to fetch"
},
"search": {
"type": "string",
"description": "Fuzzy search filter (optional)"
},
"cursor": {
"type": "string",
"description": "Cursor from the previous page's pageInfo.endCursor (omit for the first page)"
},
"pageSize": {
"type": "number",
"minimum": 1,
"description": "Results per page (default: 20)"
}
}
}
}

Tool 2: Calculate Buy Amount​

{
"name": "gala_launchpad_calculate_buy_amount",
"description": "Calculate token amounts for buying with slippage and fee breakdown",
"inputSchema": {
"type": "object",
"properties": {
"tokenName": {
"type": "string",
"pattern": "^[a-z0-9_-]{2,20}$",
"description": "Token name"
},
"amount": {
"type": "string",
"pattern": "^[0-9]+(\\.[0-9]+)?$",
"description": "Decimal string in whole units (e.g., '1' for 1 GALA, '10.5')"
},
"type": {
"type": "string",
"enum": ["native", "exact"],
"description": "native = spending GALA, exact = buying exact tokens"
}
},
"required": ["tokenName", "amount", "type"]
}
}

Tool 3: Execute Buy​

{
"name": "gala_launchpad_buy",
"description": "Execute token purchase on Gala Launchpad with slippage protection",
"inputSchema": {
"type": "object",
"properties": {
"tokenName": {
"type": "string",
"pattern": "^[a-z0-9_-]{2,20}$"
},
"amount": {
"type": "string",
"pattern": "^[0-9]+(\\.[0-9]+)?$"
},
"type": {
"type": "string",
"enum": ["native", "exact"]
},
"expectedAmount": {
"type": "string",
"pattern": "^[0-9]+(\\.[0-9]+)?$",
"description": "Expected output from calculateBuyAmount"
},
"slippageToleranceFactor": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Decimal format (0.05 = 5% slippage)"
}
},
"required": ["tokenName", "amount", "type", "expectedAmount", "slippageToleranceFactor"]
}
}

Tool 4: Fetch Balance​

{
"name": "gala_launchpad_fetch_gala_balance",
"description": "Get GALA balance for a wallet address",
"inputSchema": {
"type": "object",
"properties": {
"walletAddress": {
"type": "string",
"pattern": "^(0x[a-fA-F0-9]{40}|eth\\|[a-fA-F0-9]{40})$",
"description": "Wallet address (optional, defaults to SDK wallet)"
}
}
}
}

Tool 5: Create Comment​

{
"name": "gala_launchpad_create_comment",
"description": "Post a comment on a token pool",
"inputSchema": {
"type": "object",
"properties": {
"tokenName": {
"type": "string",
"pattern": "^[a-z0-9_-]{2,20}$"
},
"content": {
"type": "string",
"maxLength": 2000,
"description": "Comment content (max 2000 chars)"
}
},
"required": ["tokenName", "content"]
}
}

The tool catalog is in the README of @gala-chain/gala-mcp-server.


Environment Configuration​

Stage Environment​

const { sdk } = await AgentConfig.quickSetup({
environment: 'stage',
debug: true,
timeout: 60000
});

// The stage preset targets the Gala staging backends (launchpad, bundle and swap)
// and the GalaChain testnet gateway: https://gateway-testnet.galachain.com

Production Environment​

const { sdk } = await AgentConfig.quickSetup({
environment: 'prod',
debug: false,
timeout: 30000,
privateKey: process.env.PRODUCTION_WALLET!
});

// URLs used:
// - Launchpad: https://lpad-backend-prod1.defi.gala.com
// - GalaChain: https://gateway-mainnet.galachain.com
// - Bundle: https://bundle-backend-prod1.defi.gala.com
// - Swap backend: https://dex-backend-prod1.defi.gala.com

Custom Environment​

const { sdk } = await AgentConfig.quickSetup({
environment: 'prod',
baseUrl: 'https://custom-backend.example.com',
timeout: 45000
});

Testing and Validation​

Unit Test Example​

import { AgentConfig } from '@gala-chain/launchpad-sdk';

describe('Trading Agent', () => {
let sdk: Awaited<ReturnType<typeof AgentConfig.quickSetup>>['sdk'];

beforeAll(async () => {
const result = await AgentConfig.quickSetup({
environment: 'stage',
autoValidate: true
});
sdk = result.sdk;
});

afterAll(() => {
sdk.cleanup();
});

test('should fetch pools', async () => {
const result = await sdk.fetchPools({ type: 'recent', pageSize: 10 });
expect(result.items.length).toBeGreaterThan(0);
expect(result.pageInfo.hasNextPage).toBeDefined();
});

test('should calculate buy amount', async () => {
const quote = await sdk.calculateBuyAmount({
tokenName: 'testtoken',
amount: '1',
type: 'native'
});

expect(quote.amount).toBeDefined();
expect(quote.transactionFee).toBeDefined();
expect(quote.gasFee).toBeDefined();
});
});

Integration Test Example​

test('complete trading flow', async () => {
const { sdk, validation } = await AgentConfig.quickSetup({
environment: 'stage'
});

// Verify setup
expect(validation?.ready).toBe(true);
expect(validation?.capabilities.canTrade).toBe(true);

// Get quote
const quote = await sdk.calculateBuyAmount({
tokenName: 'testtoken',
amount: '1', // 1 GALA
type: 'native'
});

expect(quote.amount).toBeTruthy();

// Execute trade
const result = await sdk.buy({
tokenName: 'testtoken',
amount: '1',
type: 'native',
expectedAmount: quote.amount,
slippageToleranceFactor: 0.05
});

expect(result.transactionId).toBeTruthy();
expect(result.type).toBe('buy');
expect(result.inputAmount).toBeTruthy();

sdk.cleanup();
});

Next Steps​

  1. Read the README of @gala-chain/gala-mcp-server for the MCP tool catalog
  2. Explore docs/agent-examples/ in the package for working code samples

Support & Resources​


Built with ❤️ for AI agents and automation tools

Verified against launchpad-sdk 9.0.0 (src/LaunchpadSDK.ts, src/types, src/utils/agent-config.ts).