🤖 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
launchpad sdk gala toolsets
📖 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.
launchpad env private key quick setup agent wallet sdk config validation auto validate can trade create tokens has balance connection healthy read only multi
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
set wallet validate
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
dex backend base url launchpad price service fetch token
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.
launchpad sdk cleanup all
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.
fetch pools result list pool data token name creator address vault created at details distribution volume graph options is available symbol resolve unit eth launchpad
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? }
}
calculate buy amount calculation result sell trade expected token options fetch trades list info
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).
fetch gala balance token result options tokens held user list created profile public full name image graduated graduation rate total trades volume launch badge success engagement status is live streaming stream
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 }.
launch token result data upload image by name options update profile full private key
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
}
create comment options result update delete add reaction to remove from get comments token name user address
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 }
transfer gala data chain receipt transaction id block number token
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'
}]
});
lock tokens data result authority unlock transaction id block number token class key
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);
});
get address ethereum
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();
agent config
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_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_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_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_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_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).
launchpad sdk