@gala-chain/launchpad-mcp-server 1.24.1 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js +3 -3
- package/dist/tools/pools/index.d.ts.map +1 -1
- package/dist/tools/pools/index.js +4 -0
- package/dist/tools/pools/index.js.map +1 -1
- package/dist/tools/pools/onDexPoolCreation.d.ts +6 -0
- package/dist/tools/pools/onDexPoolCreation.d.ts.map +1 -0
- package/dist/tools/pools/onDexPoolCreation.js +60 -0
- package/dist/tools/pools/onDexPoolCreation.js.map +1 -0
- package/dist/tools/pools/onLaunchpadTokenCreation.d.ts +6 -0
- package/dist/tools/pools/onLaunchpadTokenCreation.d.ts.map +1 -0
- package/dist/tools/pools/onLaunchpadTokenCreation.js +54 -0
- package/dist/tools/pools/onLaunchpadTokenCreation.js.map +1 -0
- package/package.json +2 -2
- package/docs/AI-AGENT-PATTERNS.md +0 -555
- package/docs/CONSTRAINTS-REFERENCE.md +0 -454
- package/docs/PROMPT-TOOL-MAPPING.md +0 -352
- package/docs/examples/default-values-pattern.md +0 -240
- package/docs/examples/tool-factory-pattern.md +0 -217
- package/jest.config.js +0 -94
- package/src/__tests__/integration/fetchTokenDetails.integration.test.ts +0 -258
- package/src/__tests__/integration/poolTools.integration.test.ts +0 -185
- package/src/__tests__/server.test.ts +0 -255
- package/src/constants/mcpToolNames.ts +0 -183
- package/src/index.ts +0 -19
- package/src/prompts/__tests__/promptStructure.test.ts +0 -187
- package/src/prompts/__tests__/registry.test.ts +0 -349
- package/src/prompts/analysis.ts +0 -380
- package/src/prompts/balances.ts +0 -182
- package/src/prompts/create-token.ts +0 -123
- package/src/prompts/creation-utils.ts +0 -103
- package/src/prompts/dex-trading.ts +0 -86
- package/src/prompts/discover-tokens.ts +0 -86
- package/src/prompts/explore-dex-pools.ts +0 -138
- package/src/prompts/index.ts +0 -178
- package/src/prompts/liquidity-positions.ts +0 -237
- package/src/prompts/pools.ts +0 -496
- package/src/prompts/portfolio.ts +0 -208
- package/src/prompts/social.ts +0 -94
- package/src/prompts/trading-calculations.ts +0 -414
- package/src/prompts/trading.ts +0 -160
- package/src/prompts/transfers.ts +0 -97
- package/src/prompts/utility-tools.ts +0 -266
- package/src/prompts/utility.ts +0 -77
- package/src/prompts/utils/handlerHelpers.ts +0 -55
- package/src/prompts/utils/textTemplates.ts +0 -73
- package/src/prompts/utils/workflowTemplates.ts +0 -511
- package/src/schemas/common-schemas.ts +0 -393
- package/src/scripts/test-all-prompts.ts +0 -184
- package/src/server.ts +0 -367
- package/src/tools/__tests__/dex-tools.test.ts +0 -562
- package/src/tools/__tests__/liquidity-positions.test.ts +0 -673
- package/src/tools/balance/index.ts +0 -174
- package/src/tools/creation/index.ts +0 -182
- package/src/tools/dex/fetchAllDexPools.ts +0 -45
- package/src/tools/dex/fetchDexPools.ts +0 -58
- package/src/tools/dex/index.ts +0 -231
- package/src/tools/dex/liquidity-positions.ts +0 -547
- package/src/tools/index.ts +0 -94
- package/src/tools/pools/fetchAllPools.ts +0 -47
- package/src/tools/pools/fetchAllPriceHistory.ts +0 -119
- package/src/tools/pools/fetchPoolDetails.ts +0 -27
- package/src/tools/pools/fetchPoolDetailsForCalculation.ts +0 -22
- package/src/tools/pools/fetchPools.ts +0 -47
- package/src/tools/pools/fetchPriceHistory.ts +0 -124
- package/src/tools/pools/fetchTokenDetails.ts +0 -77
- package/src/tools/pools/index.ts +0 -284
- package/src/tools/social/index.ts +0 -64
- package/src/tools/trading/index.ts +0 -605
- package/src/tools/transfers/index.ts +0 -75
- package/src/tools/utils/clearCache.ts +0 -36
- package/src/tools/utils/createWallet.ts +0 -19
- package/src/tools/utils/explainSdkUsage.ts +0 -1446
- package/src/tools/utils/getAddress.ts +0 -12
- package/src/tools/utils/getCacheInfo.ts +0 -14
- package/src/tools/utils/getConfig.ts +0 -21
- package/src/tools/utils/getEnvironment.ts +0 -17
- package/src/tools/utils/getEthereumAddress.ts +0 -12
- package/src/tools/utils/getUrlByTokenName.ts +0 -12
- package/src/tools/utils/getVersion.ts +0 -25
- package/src/tools/utils/getWallet.ts +0 -25
- package/src/tools/utils/hasWallet.ts +0 -15
- package/src/tools/utils/index.ts +0 -37
- package/src/tools/utils/isTokenGraduated.ts +0 -16
- package/src/tools/utils/setWallet.ts +0 -41
- package/src/tools/utils/switchEnvironment.ts +0 -28
- package/src/types/mcp.ts +0 -72
- package/src/utils/__tests__/validation.test.ts +0 -147
- package/src/utils/constraints.ts +0 -155
- package/src/utils/default-values.ts +0 -208
- package/src/utils/error-handler.ts +0 -69
- package/src/utils/error-templates.ts +0 -273
- package/src/utils/response-formatter.ts +0 -51
- package/src/utils/tool-factory.ts +0 -303
- package/src/utils/tool-registry.ts +0 -296
- package/src/utils/validation.ts +0 -429
- package/tests/wallet-management-integration.test.ts +0 -284
- package/tsconfig.json +0 -23
|
@@ -1,562 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit Tests for DEX Trading MCP Tools
|
|
3
|
-
*
|
|
4
|
-
* Tests the MCP tools for DEX trading operations including:
|
|
5
|
-
* - Swap quote generation (exact input/output)
|
|
6
|
-
* - Swap execution with slippage protection
|
|
7
|
-
* - User asset queries
|
|
8
|
-
* - Pool information retrieval
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
getSwapQuoteExactInputTool,
|
|
13
|
-
getSwapQuoteExactOutputTool,
|
|
14
|
-
executeSwapTool,
|
|
15
|
-
getSwapUserAssetsTool,
|
|
16
|
-
getSwapPoolInfoTool,
|
|
17
|
-
} from '../dex/index';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Mock LaunchpadSDK
|
|
21
|
-
*/
|
|
22
|
-
const mockSdk = {
|
|
23
|
-
getSwapQuoteExactInput: jest.fn(),
|
|
24
|
-
getSwapQuoteExactOutput: jest.fn(),
|
|
25
|
-
executeSwap: jest.fn(),
|
|
26
|
-
getSwapUserAssets: jest.fn(),
|
|
27
|
-
getSwapPoolInfo: jest.fn(),
|
|
28
|
-
getAddress: jest.fn(() => 'eth|0x1234567890abcdef1234567890abcdef12345678'),
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
describe('DEX Trading MCP Tools', () => {
|
|
32
|
-
beforeEach(() => {
|
|
33
|
-
jest.clearAllMocks();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
describe('getSwapQuoteExactInputTool', () => {
|
|
37
|
-
it('should be properly configured tool', () => {
|
|
38
|
-
expect(getSwapQuoteExactInputTool).toBeDefined();
|
|
39
|
-
expect(getSwapQuoteExactInputTool.name).toBe('gala_launchpad_get_swap_quote_exact_input');
|
|
40
|
-
expect(getSwapQuoteExactInputTool.description).toContain('exact input');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should have correct input schema', () => {
|
|
44
|
-
const schema = getSwapQuoteExactInputTool.inputSchema as any;
|
|
45
|
-
expect(schema.type).toBe('object');
|
|
46
|
-
expect(schema.properties).toHaveProperty('fromToken');
|
|
47
|
-
expect(schema.properties).toHaveProperty('toToken');
|
|
48
|
-
expect(schema.properties).toHaveProperty('amount');
|
|
49
|
-
expect(schema.required).toEqual(['fromToken', 'toToken', 'amount']);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('should return formatted quote response', async () => {
|
|
53
|
-
const mockQuote = {
|
|
54
|
-
fromToken: 'GALA',
|
|
55
|
-
toToken: 'GUSDC',
|
|
56
|
-
inputAmount: '100',
|
|
57
|
-
estimatedOutput: '95.5',
|
|
58
|
-
feeTier: 3000,
|
|
59
|
-
priceImpact: 0.005,
|
|
60
|
-
executionPrice: 0.955,
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
mockSdk.getSwapQuoteExactInput.mockResolvedValueOnce(mockQuote);
|
|
64
|
-
|
|
65
|
-
const handler = getSwapQuoteExactInputTool.handler as any;
|
|
66
|
-
const result = await handler(mockSdk, {
|
|
67
|
-
fromToken: 'GALA',
|
|
68
|
-
toToken: 'GUSDC',
|
|
69
|
-
amount: '100',
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
expect(result).toBeDefined();
|
|
73
|
-
expect(result.content).toBeDefined();
|
|
74
|
-
expect(result.content[0].type).toBe('text');
|
|
75
|
-
expect(result.content[0].text).toContain('GALA');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should handle quote errors gracefully', async () => {
|
|
79
|
-
mockSdk.getSwapQuoteExactInput.mockRejectedValueOnce(
|
|
80
|
-
new Error('Pool not found')
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
const handler = getSwapQuoteExactInputTool.handler as any;
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
await handler(mockSdk, {
|
|
87
|
-
fromToken: 'GALA',
|
|
88
|
-
toToken: 'INVALID',
|
|
89
|
-
amount: '100',
|
|
90
|
-
});
|
|
91
|
-
throw new Error('Should have thrown error');
|
|
92
|
-
} catch (error) {
|
|
93
|
-
expect(error).toBeDefined();
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
describe('getSwapQuoteExactOutputTool', () => {
|
|
99
|
-
it('should be properly configured tool', () => {
|
|
100
|
-
expect(getSwapQuoteExactOutputTool).toBeDefined();
|
|
101
|
-
expect(getSwapQuoteExactOutputTool.name).toBe('gala_launchpad_get_swap_quote_exact_output');
|
|
102
|
-
expect(getSwapQuoteExactOutputTool.description).toContain('exact output');
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('should have correct input schema', () => {
|
|
106
|
-
const schema = getSwapQuoteExactOutputTool.inputSchema as any;
|
|
107
|
-
expect(schema.required).toEqual(['fromToken', 'toToken', 'amount']);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('should return formatted quote for desired output', async () => {
|
|
111
|
-
const mockQuote = {
|
|
112
|
-
fromToken: 'GALA',
|
|
113
|
-
toToken: 'GUSDC',
|
|
114
|
-
inputAmount: '104.7',
|
|
115
|
-
estimatedOutput: '100',
|
|
116
|
-
feeTier: 3000,
|
|
117
|
-
priceImpact: 0.006,
|
|
118
|
-
executionPrice: 0.954,
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
mockSdk.getSwapQuoteExactOutput.mockResolvedValueOnce(mockQuote);
|
|
122
|
-
|
|
123
|
-
const handler = getSwapQuoteExactOutputTool.handler as any;
|
|
124
|
-
const result = await handler(mockSdk, {
|
|
125
|
-
fromToken: 'GALA',
|
|
126
|
-
toToken: 'GUSDC',
|
|
127
|
-
amount: '100',
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
expect(result).toBeDefined();
|
|
131
|
-
expect(result.content[0].text).toContain('100');
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
describe('executeSwapTool', () => {
|
|
136
|
-
it('should be properly configured tool', () => {
|
|
137
|
-
expect(executeSwapTool).toBeDefined();
|
|
138
|
-
expect(executeSwapTool.name).toBe('gala_launchpad_execute_swap');
|
|
139
|
-
expect(executeSwapTool.description).toContain('Execute a token swap');
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('should have correct input schema with required fields', () => {
|
|
143
|
-
const schema = executeSwapTool.inputSchema as any;
|
|
144
|
-
expect(schema.properties).toHaveProperty('fromToken');
|
|
145
|
-
expect(schema.properties).toHaveProperty('toToken');
|
|
146
|
-
expect(schema.properties).toHaveProperty('inputAmount');
|
|
147
|
-
expect(schema.properties).toHaveProperty('estimatedOutput');
|
|
148
|
-
expect(schema.properties).toHaveProperty('feeTier');
|
|
149
|
-
expect(schema.required).toEqual([
|
|
150
|
-
'fromToken',
|
|
151
|
-
'toToken',
|
|
152
|
-
'inputAmount',
|
|
153
|
-
'estimatedOutput',
|
|
154
|
-
'feeTier',
|
|
155
|
-
]);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('should have default slippage tolerance', () => {
|
|
159
|
-
const schema = executeSwapTool.inputSchema as any;
|
|
160
|
-
expect(schema.properties.slippageTolerance.default).toBe(0.01);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('should validate wallet before execution', async () => {
|
|
164
|
-
mockSdk.getAddress.mockImplementationOnce(() => {
|
|
165
|
-
throw new Error('Wallet not configured');
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
const handler = executeSwapTool.handler as any;
|
|
169
|
-
|
|
170
|
-
const result = await handler(mockSdk, {
|
|
171
|
-
fromToken: 'GALA',
|
|
172
|
-
toToken: 'GUSDC',
|
|
173
|
-
inputAmount: '100',
|
|
174
|
-
estimatedOutput: '95.5',
|
|
175
|
-
feeTier: 3000,
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// The error should be wrapped by withErrorHandling
|
|
179
|
-
expect(result).toBeDefined();
|
|
180
|
-
// Check for error response structure
|
|
181
|
-
expect(result.content).toBeDefined();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it('should execute swap with default slippage', async () => {
|
|
185
|
-
const mockResult = {
|
|
186
|
-
transactionId: 'tx-123',
|
|
187
|
-
status: 'COMPLETED',
|
|
188
|
-
fromToken: 'GALA',
|
|
189
|
-
toToken: 'GUSDC',
|
|
190
|
-
inputAmount: '100',
|
|
191
|
-
outputAmount: '95.5',
|
|
192
|
-
feeTier: 3000,
|
|
193
|
-
slippageTolerance: 0.01,
|
|
194
|
-
timestamp: new Date(),
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
mockSdk.executeSwap.mockResolvedValueOnce(mockResult);
|
|
198
|
-
|
|
199
|
-
const handler = executeSwapTool.handler as any;
|
|
200
|
-
const result = await handler(mockSdk, {
|
|
201
|
-
fromToken: 'GALA',
|
|
202
|
-
toToken: 'GUSDC',
|
|
203
|
-
inputAmount: '100',
|
|
204
|
-
estimatedOutput: '95.5',
|
|
205
|
-
feeTier: 3000,
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
expect(result).toBeDefined();
|
|
209
|
-
expect(result.content[0].text).toContain('tx-123');
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it('should execute swap with custom slippage tolerance', async () => {
|
|
213
|
-
const mockResult = {
|
|
214
|
-
transactionId: 'tx-456',
|
|
215
|
-
status: 'COMPLETED',
|
|
216
|
-
fromToken: 'GALA',
|
|
217
|
-
toToken: 'GUSDC',
|
|
218
|
-
inputAmount: '100',
|
|
219
|
-
outputAmount: '93.5',
|
|
220
|
-
feeTier: 3000,
|
|
221
|
-
slippageTolerance: 0.05,
|
|
222
|
-
timestamp: new Date(),
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
mockSdk.executeSwap.mockResolvedValueOnce(mockResult);
|
|
226
|
-
|
|
227
|
-
const handler = executeSwapTool.handler as any;
|
|
228
|
-
const result = await handler(mockSdk, {
|
|
229
|
-
fromToken: 'GALA',
|
|
230
|
-
toToken: 'GUSDC',
|
|
231
|
-
inputAmount: '100',
|
|
232
|
-
estimatedOutput: '95.5',
|
|
233
|
-
feeTier: 3000,
|
|
234
|
-
slippageTolerance: 0.05,
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
expect(result).toBeDefined();
|
|
238
|
-
expect(mockSdk.executeSwap).toHaveBeenCalledWith(
|
|
239
|
-
'GALA',
|
|
240
|
-
'GUSDC',
|
|
241
|
-
'100',
|
|
242
|
-
'95.5',
|
|
243
|
-
3000,
|
|
244
|
-
0.05
|
|
245
|
-
);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
it('should handle swap execution errors', async () => {
|
|
249
|
-
mockSdk.executeSwap.mockRejectedValueOnce(
|
|
250
|
-
new Error('Insufficient balance')
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
const handler = executeSwapTool.handler as any;
|
|
254
|
-
|
|
255
|
-
const result = await handler(mockSdk, {
|
|
256
|
-
fromToken: 'GALA',
|
|
257
|
-
toToken: 'GUSDC',
|
|
258
|
-
inputAmount: '100',
|
|
259
|
-
estimatedOutput: '95.5',
|
|
260
|
-
feeTier: 3000,
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
// The error should be wrapped by withErrorHandling
|
|
264
|
-
expect(result).toBeDefined();
|
|
265
|
-
// Check for error response structure
|
|
266
|
-
expect(result.content).toBeDefined();
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
describe('getSwapUserAssetsTool', () => {
|
|
271
|
-
it('should be properly configured tool', () => {
|
|
272
|
-
expect(getSwapUserAssetsTool).toBeDefined();
|
|
273
|
-
expect(getSwapUserAssetsTool.name).toBe('gala_launchpad_get_swap_user_assets');
|
|
274
|
-
expect(getSwapUserAssetsTool.description).toContain('token assets');
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
it('should have correct input schema', () => {
|
|
278
|
-
const schema = getSwapUserAssetsTool.inputSchema as any;
|
|
279
|
-
expect(schema.properties).toHaveProperty('walletAddress');
|
|
280
|
-
expect(schema.required).toEqual(['walletAddress']);
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
it('should return formatted asset list', async () => {
|
|
284
|
-
const mockAssets = [
|
|
285
|
-
{ symbol: 'GALA', balance: '1000', decimals: 8 },
|
|
286
|
-
{ symbol: 'GUSDC', balance: '500.5', decimals: 6 },
|
|
287
|
-
];
|
|
288
|
-
|
|
289
|
-
mockSdk.getSwapUserAssets.mockResolvedValueOnce(mockAssets);
|
|
290
|
-
|
|
291
|
-
const handler = getSwapUserAssetsTool.handler as any;
|
|
292
|
-
const result = await handler(mockSdk, {
|
|
293
|
-
walletAddress: 'eth|0x1234567890abcdef1234567890abcdef12345678',
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
expect(result).toBeDefined();
|
|
297
|
-
expect(result.content[0].text).toContain('GALA');
|
|
298
|
-
expect(result.content[0].text).toContain('GUSDC');
|
|
299
|
-
expect(result.content[0].text).toContain('2 assets');
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it('should handle empty asset list', async () => {
|
|
303
|
-
mockSdk.getSwapUserAssets.mockResolvedValueOnce([]);
|
|
304
|
-
|
|
305
|
-
const handler = getSwapUserAssetsTool.handler as any;
|
|
306
|
-
const result = await handler(mockSdk, {
|
|
307
|
-
walletAddress: 'eth|0xnewwallet',
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
expect(result).toBeDefined();
|
|
311
|
-
expect(result.content[0].text).toContain('0 assets');
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
it('should handle asset query errors', async () => {
|
|
315
|
-
mockSdk.getSwapUserAssets.mockRejectedValueOnce(
|
|
316
|
-
new Error('Invalid wallet address')
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
const handler = getSwapUserAssetsTool.handler as any;
|
|
320
|
-
|
|
321
|
-
try {
|
|
322
|
-
await handler(mockSdk, {
|
|
323
|
-
walletAddress: 'eth|invalid',
|
|
324
|
-
});
|
|
325
|
-
fail('Should have thrown error');
|
|
326
|
-
} catch (error) {
|
|
327
|
-
expect(error).toBeDefined();
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
describe('getSwapPoolInfoTool', () => {
|
|
333
|
-
it('should be properly configured tool', () => {
|
|
334
|
-
expect(getSwapPoolInfoTool).toBeDefined();
|
|
335
|
-
expect(getSwapPoolInfoTool.name).toBe('gala_launchpad_get_swap_pool_info');
|
|
336
|
-
expect(getSwapPoolInfoTool.description).toContain('liquidity');
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
it('should have correct input schema', () => {
|
|
340
|
-
const schema = getSwapPoolInfoTool.inputSchema as any;
|
|
341
|
-
expect(schema.properties).toHaveProperty('tokenA');
|
|
342
|
-
expect(schema.properties).toHaveProperty('tokenB');
|
|
343
|
-
expect(schema.required).toEqual(['tokenA', 'tokenB']);
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
it('should return formatted pool information', async () => {
|
|
347
|
-
const mockPoolInfo = {
|
|
348
|
-
tokenA: 'GALA',
|
|
349
|
-
tokenB: 'GUSDC',
|
|
350
|
-
liquidity: '50000000',
|
|
351
|
-
feeTiers: [500, 3000, 10000],
|
|
352
|
-
swapCount: 1250,
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
mockSdk.getSwapPoolInfo.mockResolvedValueOnce(mockPoolInfo);
|
|
356
|
-
|
|
357
|
-
const handler = getSwapPoolInfoTool.handler as any;
|
|
358
|
-
const result = await handler(mockSdk, {
|
|
359
|
-
tokenA: 'GALA',
|
|
360
|
-
tokenB: 'GUSDC',
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
expect(result).toBeDefined();
|
|
364
|
-
expect(result.content[0].text).toContain('50000000');
|
|
365
|
-
expect(result.content[0].text).toContain('5%');
|
|
366
|
-
expect(result.content[0].text).toContain('30%');
|
|
367
|
-
expect(result.content[0].text).toContain('100%');
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
it('should handle multiple fee tiers', async () => {
|
|
371
|
-
const mockPoolInfo = {
|
|
372
|
-
tokenA: 'GALA',
|
|
373
|
-
tokenB: 'GUSDC',
|
|
374
|
-
liquidity: '100000000',
|
|
375
|
-
feeTiers: [100, 500, 3000, 10000],
|
|
376
|
-
swapCount: 5000,
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
mockSdk.getSwapPoolInfo.mockResolvedValueOnce(mockPoolInfo);
|
|
380
|
-
|
|
381
|
-
const handler = getSwapPoolInfoTool.handler as any;
|
|
382
|
-
const result = await handler(mockSdk, {
|
|
383
|
-
tokenA: 'GALA',
|
|
384
|
-
tokenB: 'GUSDC',
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
expect(result).toBeDefined();
|
|
388
|
-
expect(result.content[0].text).toContain('4 fee tiers');
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
it('should handle pool not found errors', async () => {
|
|
392
|
-
mockSdk.getSwapPoolInfo.mockRejectedValueOnce(
|
|
393
|
-
new Error('Pool not found')
|
|
394
|
-
);
|
|
395
|
-
|
|
396
|
-
const handler = getSwapPoolInfoTool.handler as any;
|
|
397
|
-
|
|
398
|
-
try {
|
|
399
|
-
await handler(mockSdk, {
|
|
400
|
-
tokenA: 'UNKNOWN',
|
|
401
|
-
tokenB: 'INVALID',
|
|
402
|
-
});
|
|
403
|
-
fail('Should have thrown error');
|
|
404
|
-
} catch (error) {
|
|
405
|
-
expect(error).toBeDefined();
|
|
406
|
-
}
|
|
407
|
-
});
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
describe('Tool Input Validation', () => {
|
|
411
|
-
it('should have valid input schemas for all tools', () => {
|
|
412
|
-
const tools = [
|
|
413
|
-
getSwapQuoteExactInputTool,
|
|
414
|
-
getSwapQuoteExactOutputTool,
|
|
415
|
-
executeSwapTool,
|
|
416
|
-
getSwapUserAssetsTool,
|
|
417
|
-
getSwapPoolInfoTool,
|
|
418
|
-
];
|
|
419
|
-
|
|
420
|
-
tools.forEach((tool) => {
|
|
421
|
-
expect(tool.inputSchema).toBeDefined();
|
|
422
|
-
const schema = tool.inputSchema as any;
|
|
423
|
-
expect(schema.type).toBe('object');
|
|
424
|
-
expect(schema.properties).toBeDefined();
|
|
425
|
-
expect(schema.required).toBeDefined();
|
|
426
|
-
expect(Array.isArray(schema.required)).toBe(true);
|
|
427
|
-
});
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
it('should define token symbol schema correctly', () => {
|
|
431
|
-
const schema = getSwapQuoteExactInputTool.inputSchema as any;
|
|
432
|
-
const fromTokenSchema = schema.properties.fromToken;
|
|
433
|
-
|
|
434
|
-
expect(fromTokenSchema.type).toBe('string');
|
|
435
|
-
expect(fromTokenSchema.minLength).toBeGreaterThan(0);
|
|
436
|
-
expect(fromTokenSchema.maxLength).toBeGreaterThan(0);
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
it('should define amount schema correctly', () => {
|
|
440
|
-
const schema = getSwapQuoteExactInputTool.inputSchema as any;
|
|
441
|
-
const amountSchema = schema.properties.amount;
|
|
442
|
-
|
|
443
|
-
expect(amountSchema).toBeDefined();
|
|
444
|
-
// Should accept numeric strings
|
|
445
|
-
expect(amountSchema.type).toBe('string');
|
|
446
|
-
});
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
describe('Error Response Formatting', () => {
|
|
450
|
-
it('should return error response with proper structure', async () => {
|
|
451
|
-
mockSdk.getSwapQuoteExactInput.mockRejectedValueOnce(
|
|
452
|
-
new Error('Network error')
|
|
453
|
-
);
|
|
454
|
-
|
|
455
|
-
const handler = getSwapQuoteExactInputTool.handler as any;
|
|
456
|
-
|
|
457
|
-
try {
|
|
458
|
-
await handler(mockSdk, {
|
|
459
|
-
fromToken: 'GALA',
|
|
460
|
-
toToken: 'GUSDC',
|
|
461
|
-
amount: '100',
|
|
462
|
-
});
|
|
463
|
-
} catch (error) {
|
|
464
|
-
expect(error).toBeDefined();
|
|
465
|
-
expect((error as Error).message).toContain('Network');
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
describe('Tool Metadata', () => {
|
|
471
|
-
it('should have descriptive tool names', () => {
|
|
472
|
-
expect(getSwapQuoteExactInputTool.name).toMatch(/^gala_launchpad_/);
|
|
473
|
-
expect(getSwapQuoteExactOutputTool.name).toMatch(/^gala_launchpad_/);
|
|
474
|
-
expect(executeSwapTool.name).toMatch(/^gala_launchpad_/);
|
|
475
|
-
expect(getSwapUserAssetsTool.name).toMatch(/^gala_launchpad_/);
|
|
476
|
-
expect(getSwapPoolInfoTool.name).toMatch(/^gala_launchpad_/);
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
it('should have clear descriptions', () => {
|
|
480
|
-
const tools = [
|
|
481
|
-
getSwapQuoteExactInputTool,
|
|
482
|
-
getSwapQuoteExactOutputTool,
|
|
483
|
-
executeSwapTool,
|
|
484
|
-
getSwapUserAssetsTool,
|
|
485
|
-
getSwapPoolInfoTool,
|
|
486
|
-
];
|
|
487
|
-
|
|
488
|
-
tools.forEach((tool) => {
|
|
489
|
-
expect(tool.description).toBeDefined();
|
|
490
|
-
expect(tool.description.length).toBeGreaterThan(10);
|
|
491
|
-
});
|
|
492
|
-
});
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
describe('Real-World Scenarios', () => {
|
|
496
|
-
it('should handle typical buy token workflow', async () => {
|
|
497
|
-
// Step 1: Get quote
|
|
498
|
-
const mockQuote = {
|
|
499
|
-
fromToken: 'GALA',
|
|
500
|
-
toToken: 'GUSDC',
|
|
501
|
-
inputAmount: '100',
|
|
502
|
-
estimatedOutput: '95.5',
|
|
503
|
-
feeTier: 3000,
|
|
504
|
-
priceImpact: 0.005,
|
|
505
|
-
executionPrice: 0.955,
|
|
506
|
-
};
|
|
507
|
-
|
|
508
|
-
mockSdk.getSwapQuoteExactInput.mockResolvedValueOnce(mockQuote);
|
|
509
|
-
const quoteHandler = getSwapQuoteExactInputTool.handler as any;
|
|
510
|
-
const quoteResult = await quoteHandler(mockSdk, {
|
|
511
|
-
fromToken: 'GALA',
|
|
512
|
-
toToken: 'GUSDC',
|
|
513
|
-
amount: '100',
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
expect(quoteResult).toBeDefined();
|
|
517
|
-
|
|
518
|
-
// Step 2: Execute swap
|
|
519
|
-
const mockSwapResult = {
|
|
520
|
-
transactionId: 'tx-123',
|
|
521
|
-
status: 'COMPLETED',
|
|
522
|
-
fromToken: 'GALA',
|
|
523
|
-
toToken: 'GUSDC',
|
|
524
|
-
inputAmount: '100',
|
|
525
|
-
outputAmount: '95.5',
|
|
526
|
-
feeTier: 3000,
|
|
527
|
-
slippageTolerance: 0.01,
|
|
528
|
-
timestamp: new Date(),
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
mockSdk.executeSwap.mockResolvedValueOnce(mockSwapResult);
|
|
532
|
-
const swapHandler = executeSwapTool.handler as any;
|
|
533
|
-
const swapResult = await swapHandler(mockSdk, {
|
|
534
|
-
fromToken: 'GALA',
|
|
535
|
-
toToken: 'GUSDC',
|
|
536
|
-
inputAmount: '100',
|
|
537
|
-
estimatedOutput: '95.5',
|
|
538
|
-
feeTier: 3000,
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
expect(swapResult).toBeDefined();
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
it('should handle portfolio view workflow', async () => {
|
|
545
|
-
const mockAssets = [
|
|
546
|
-
{ symbol: 'GALA', balance: '5000', decimals: 8 },
|
|
547
|
-
{ symbol: 'GUSDC', balance: '2500.75', decimals: 6 },
|
|
548
|
-
{ symbol: 'anime', balance: '1000000', decimals: 8 },
|
|
549
|
-
];
|
|
550
|
-
|
|
551
|
-
mockSdk.getSwapUserAssets.mockResolvedValueOnce(mockAssets);
|
|
552
|
-
|
|
553
|
-
const handler = getSwapUserAssetsTool.handler as any;
|
|
554
|
-
const result = await handler(mockSdk, {
|
|
555
|
-
walletAddress: 'eth|0xwalletaddress',
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
expect(result).toBeDefined();
|
|
559
|
-
expect(result.content[0].text).toContain('3 assets');
|
|
560
|
-
});
|
|
561
|
-
});
|
|
562
|
-
});
|