🤖 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
- Quick Start for AI Agents
- SDK Architecture Overview
- Complete Method Catalog
- Common AI Agent Workflows
- Type Reference for Code Generation
- Error Handling Patterns
- Best Practices for Agent Implementation
- Example MCP Tool Schemas
- Environment Configuration
- 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?
- Auto-detected environment from
LAUNCHPAD_ENVorENVIRONMENT(stageorprod), defaulting toprod - Created or imported wallet from
process.env.PRIVATE_KEYor generated new one - Configured SDK with appropriate timeouts and debug settings
- Validated setup including balance checks and connectivity tests
- 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):
-
LaunchpadService →
https://lpad-backend-{env}.defi.gala.com- Pool management, trade history, comments, profiles
-
GalaChainService →
https://galachain-gateway-{env}.galachain.com- Balances, transfers, blockchain operations
-
Swap backend (
dexBackendBaseUrl) → thestagepreset, prodhttps://dex-backend-prod1.defi.gala.com- Read-only:
LaunchpadPriceServicereadsGET /market/pricefor the USD price of a launchpad token (fetchTokenPrice). DEX quotes, pools, positions and market data are gswap-sdk's, not this SDK's
- Read-only:
-
BundleService →
https://bundle-backend-{env}.defi.gala.com- Token trading, transaction bundling
-
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
LaunchpadSDKclass has 343 public instance methods (plus theeventsandrealtimegetters and the staticcleanupAll), counted from the class body of the builtdist/LaunchpadSDK.d.ts: every method declared in the class that is notprivate/protected/static. They also cover bridging, streaming, chat, session auth and more. GSwap DEX trading is gswap-sdk'sGSwapclient (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
- Read the README of
@gala-chain/gala-mcp-serverfor the MCP tool catalog - Explore
docs/agent-examples/in the package for working code samples
Support & Resources
- SDK Documentation: README.md
- API Reference: API-REFERENCE.md
- Package: @gala-chain/launchpad-sdk
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).