@gala-chain/launchpad-mcp-server 5.1.1 → 7.0.0-beta.1
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/README.md +57 -113
- package/dist/constants/mcpToolNames.d.ts +2 -2
- package/dist/constants/mcpToolNames.d.ts.map +1 -1
- package/dist/constants/mcpToolNames.js +1 -1
- package/dist/constants/mcpToolNames.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.d.ts.map +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/generated/version.js.map +1 -1
- package/dist/prompts/analysis.d.ts.map +1 -1
- package/dist/prompts/analysis.js +5 -13
- package/dist/prompts/analysis.js.map +1 -1
- package/dist/prompts/dex-trading.d.ts.map +1 -1
- package/dist/prompts/dex-trading.js +10 -8
- package/dist/prompts/dex-trading.js.map +1 -1
- package/dist/prompts/manifest.d.ts +2 -2
- package/dist/prompts/manifest.d.ts.map +1 -1
- package/dist/prompts/manifest.js +5 -12
- package/dist/prompts/manifest.js.map +1 -1
- package/dist/prompts/tier1-token-analysis.d.ts +0 -4
- package/dist/prompts/tier1-token-analysis.d.ts.map +1 -1
- package/dist/prompts/tier1-token-analysis.js +2 -87
- package/dist/prompts/tier1-token-analysis.js.map +1 -1
- package/dist/prompts/utility-tools.js +1 -1
- package/dist/prompts/utility-tools.js.map +1 -1
- package/dist/prompts/utility.d.ts +1 -1
- package/dist/prompts/utility.d.ts.map +1 -1
- package/dist/prompts/utility.js +7 -8
- package/dist/prompts/utility.js.map +1 -1
- package/dist/scripts/test-all-prompts.js +2 -44
- package/dist/scripts/test-all-prompts.js.map +1 -1
- package/dist/server.d.ts +4 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +13 -6
- package/dist/server.js.map +1 -1
- package/dist/tools/chat/index.d.ts +0 -14
- package/dist/tools/chat/index.d.ts.map +1 -1
- package/dist/tools/chat/index.js +1 -79
- package/dist/tools/chat/index.js.map +1 -1
- package/dist/tools/creation/index.d.ts.map +1 -1
- package/dist/tools/creation/index.js +10 -2
- package/dist/tools/creation/index.js.map +1 -1
- package/dist/tools/dex/helpers.d.ts +20 -419
- package/dist/tools/dex/helpers.d.ts.map +1 -1
- package/dist/tools/dex/helpers.js +127 -542
- package/dist/tools/dex/helpers.js.map +1 -1
- package/dist/tools/dex/index.d.ts +2 -51
- package/dist/tools/dex/index.d.ts.map +1 -1
- package/dist/tools/dex/index.js +144 -131
- package/dist/tools/dex/index.js.map +1 -1
- package/dist/tools/dex-liquidity/index.d.ts +1 -9
- package/dist/tools/dex-liquidity/index.d.ts.map +1 -1
- package/dist/tools/dex-liquidity/index.js +107 -310
- package/dist/tools/dex-liquidity/index.js.map +1 -1
- package/dist/tools/dex-pools/index.d.ts +1 -50
- package/dist/tools/dex-pools/index.d.ts.map +1 -1
- package/dist/tools/dex-pools/index.js +69 -173
- package/dist/tools/dex-pools/index.js.map +1 -1
- package/dist/tools/global-feed/getGlobalFeedStatus.d.ts.map +1 -1
- package/dist/tools/global-feed/getGlobalFeedStatus.js +2 -3
- package/dist/tools/global-feed/getGlobalFeedStatus.js.map +1 -1
- package/dist/tools/global-feed/monitorGlobalFeedEvents.d.ts.map +1 -1
- package/dist/tools/global-feed/monitorGlobalFeedEvents.js +2 -3
- package/dist/tools/global-feed/monitorGlobalFeedEvents.js.map +1 -1
- package/dist/tools/global-feed/subscribeToGlobalFeed.d.ts.map +1 -1
- package/dist/tools/global-feed/subscribeToGlobalFeed.js +3 -4
- package/dist/tools/global-feed/subscribeToGlobalFeed.js.map +1 -1
- package/dist/tools/global-feed/unsubscribeFromGlobalFeed.js +3 -3
- package/dist/tools/global-feed/unsubscribeFromGlobalFeed.js.map +1 -1
- package/dist/tools/handler-factories.d.ts +27 -15
- package/dist/tools/handler-factories.d.ts.map +1 -1
- package/dist/tools/handler-factories.js +58 -23
- package/dist/tools/handler-factories.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +16 -49
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/manifest.d.ts +3 -3
- package/dist/tools/manifest.d.ts.map +1 -1
- package/dist/tools/manifest.js +242 -98
- package/dist/tools/manifest.js.map +1 -1
- package/dist/tools/messages/getPinnedMessage.d.ts +1 -1
- package/dist/tools/messages/getPinnedMessage.js +1 -1
- package/dist/tools/messages/index.d.ts +1 -1
- package/dist/tools/messages/index.js +1 -1
- package/dist/tools/messages/pinMessage.d.ts +1 -1
- package/dist/tools/messages/pinMessage.js +1 -1
- package/dist/tools/messages/unpinMessage.d.ts +1 -1
- package/dist/tools/messages/unpinMessage.js +1 -1
- package/dist/tools/pagination-handler-factory.d.ts +6 -6
- package/dist/tools/pagination-handler-factory.js +6 -6
- package/dist/tools/pools/index.d.ts +0 -1
- package/dist/tools/pools/index.d.ts.map +1 -1
- package/dist/tools/pools/index.js +4 -11
- package/dist/tools/pools/index.js.map +1 -1
- package/dist/tools/trading/index.d.ts.map +1 -1
- package/dist/tools/trading/index.js +37 -4
- package/dist/tools/trading/index.js.map +1 -1
- package/dist/tools/utils/explainSdkUsage.d.ts +3 -104
- package/dist/tools/utils/explainSdkUsage.d.ts.map +1 -1
- package/dist/tools/utils/explainSdkUsage.js +301 -7036
- package/dist/tools/utils/explainSdkUsage.js.map +1 -1
- package/dist/tools/utils/getEnvironment.d.ts +1 -1
- package/dist/tools/utils/getEnvironment.js +2 -2
- package/dist/tools/utils/getEnvironment.js.map +1 -1
- package/dist/tools/utils/switchEnvironment.d.ts +1 -1
- package/dist/tools/utils/switchEnvironment.d.ts.map +1 -1
- package/dist/tools/utils/switchEnvironment.js +8 -5
- package/dist/tools/utils/switchEnvironment.js.map +1 -1
- package/dist/utils/error-templates.d.ts +10 -0
- package/dist/utils/error-templates.d.ts.map +1 -1
- package/dist/utils/error-templates.js +29 -1
- package/dist/utils/error-templates.js.map +1 -1
- package/dist/utils/pool-filter-builder.d.ts +1 -1
- package/dist/utils/pool-filter-builder.js +1 -1
- package/dist/utils/response-formatter.d.ts +16 -1
- package/dist/utils/response-formatter.d.ts.map +1 -1
- package/dist/utils/response-formatter.js +49 -2
- package/dist/utils/response-formatter.js.map +1 -1
- package/package.json +7 -6
- package/dist/tools/chat/getPinnedChatMessage.d.ts +0 -15
- package/dist/tools/chat/getPinnedChatMessage.d.ts.map +0 -1
- package/dist/tools/chat/getPinnedChatMessage.js +0 -37
- package/dist/tools/chat/getPinnedChatMessage.js.map +0 -1
- package/dist/tools/chat/pinChatMessage.d.ts +0 -16
- package/dist/tools/chat/pinChatMessage.d.ts.map +0 -1
- package/dist/tools/chat/pinChatMessage.js +0 -51
- package/dist/tools/chat/pinChatMessage.js.map +0 -1
- package/dist/tools/chat/unpinChatMessage.d.ts +0 -16
- package/dist/tools/chat/unpinChatMessage.d.ts.map +0 -1
- package/dist/tools/chat/unpinChatMessage.js +0 -39
- package/dist/tools/chat/unpinChatMessage.js.map +0 -1
|
@@ -1,520 +1,68 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* DEX Helper Utilities
|
|
4
|
-
*
|
|
5
|
-
* Shared formatting and validation functions for DEX tools.
|
|
6
|
-
* Reduces duplication across quote, position, volume, and swap tools.
|
|
7
|
-
*
|
|
8
|
-
* Contains:
|
|
9
|
-
* - Quote response formatting (SwapQuoteResult, DexPoolQuoteResult)
|
|
10
|
-
* - Liquidity position formatting
|
|
11
|
-
* - Wallet validation
|
|
12
|
-
* - Volume trend analysis
|
|
13
|
-
* - Token asset mapping
|
|
14
|
-
* - Handler factories for quote tools
|
|
15
|
-
*/
|
|
2
|
+
/** Shared formatting and argument helpers for the v6 GSwap MCP tools. */
|
|
16
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.VALID_FEE_TIERS = void 0;
|
|
18
|
-
exports.formatQuoteResponse = formatQuoteResponse;
|
|
19
|
-
exports.formatDexPoolQuoteResponse = formatDexPoolQuoteResponse;
|
|
20
|
-
exports.formatPosition = formatPosition;
|
|
21
|
-
exports.formatPositions = formatPositions;
|
|
22
|
-
exports.validateWalletConfigured = validateWalletConfigured;
|
|
23
|
-
exports.formatVolumeTrends = formatVolumeTrends;
|
|
24
|
-
exports.mapTokenAssets = mapTokenAssets;
|
|
25
|
-
exports.formatFeeTierPercent = formatFeeTierPercent;
|
|
26
|
-
exports.formatFeeTiersPercent = formatFeeTiersPercent;
|
|
27
|
-
exports.validateFeeTier = validateFeeTier;
|
|
28
4
|
exports.extractTokenPairParams = extractTokenPairParams;
|
|
29
5
|
exports.extractTokenPairWithTicksParams = extractTokenPairWithTicksParams;
|
|
30
|
-
exports.
|
|
6
|
+
exports.mapTokenAssets = mapTokenAssets;
|
|
31
7
|
exports.mapTokenMetadataArray = mapTokenMetadataArray;
|
|
32
|
-
exports.
|
|
33
|
-
exports.
|
|
34
|
-
exports.formatAddLiquidityResponse = formatAddLiquidityResponse;
|
|
8
|
+
exports.formatFeeTierPercent = formatFeeTierPercent;
|
|
9
|
+
exports.formatFeeTiersPercent = formatFeeTiersPercent;
|
|
35
10
|
exports.createSwapQuoteTool = createSwapQuoteTool;
|
|
36
11
|
exports.createDexPoolQuoteTool = createDexPoolQuoteTool;
|
|
37
|
-
|
|
12
|
+
exports.formatPosition = formatPosition;
|
|
13
|
+
exports.formatPositions = formatPositions;
|
|
14
|
+
exports.formatPool = formatPool;
|
|
15
|
+
exports.formatSlot0 = formatSlot0;
|
|
16
|
+
exports.formatDexSubmission = formatDexSubmission;
|
|
17
|
+
exports.asPriceIn = asPriceIn;
|
|
38
18
|
const response_formatter_js_1 = require("../../utils/response-formatter.js");
|
|
39
19
|
const error_handler_js_1 = require("../../utils/error-handler.js");
|
|
40
20
|
const common_schemas_js_1 = require("../../schemas/common-schemas.js");
|
|
41
|
-
/**
|
|
42
|
-
* Build a standardized quote message.
|
|
43
|
-
*
|
|
44
|
-
* Centralizes the message format pattern used by all quote response formatters.
|
|
45
|
-
* Format: "{prefix} {inputAmount} {fromToken} -> ~{outputAmount} {toToken}{suffix}"
|
|
46
|
-
*
|
|
47
|
-
* @param data - Quote data with tokens and amounts
|
|
48
|
-
* @param options - Message formatting options
|
|
49
|
-
* @returns Formatted quote message string
|
|
50
|
-
*/
|
|
51
|
-
function buildQuoteMessage(data, options) {
|
|
52
|
-
const { fromToken, toToken, inputAmount, outputAmount } = data;
|
|
53
|
-
const { prefix, suffix = '' } = options;
|
|
54
|
-
return `${prefix} ${inputAmount} ${fromToken} -> ~${outputAmount} ${toToken}${suffix}`;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Format a swap quote response with standardized fields.
|
|
58
|
-
*
|
|
59
|
-
* Handles SwapQuoteResult (from getSwapQuote* methods).
|
|
60
|
-
* Adds optional calculationMode for context.
|
|
61
|
-
*
|
|
62
|
-
* @param quote - The quote result to format (SwapQuoteResult)
|
|
63
|
-
* @param mode - Optional calculation mode (e.g., 'local', 'external')
|
|
64
|
-
* @returns Formatted response object with common quote fields
|
|
65
|
-
*/
|
|
66
|
-
function formatQuoteResponse(quote, mode) {
|
|
67
|
-
return {
|
|
68
|
-
fromToken: quote.fromToken,
|
|
69
|
-
toToken: quote.toToken,
|
|
70
|
-
inputAmount: quote.inputAmount,
|
|
71
|
-
estimatedOutput: quote.estimatedOutput,
|
|
72
|
-
feeTier: quote.feeTier,
|
|
73
|
-
priceImpact: quote.priceImpact,
|
|
74
|
-
executionPrice: quote.executionPrice,
|
|
75
|
-
...(mode !== undefined && mode !== '' && { calculationMode: mode }),
|
|
76
|
-
message: buildQuoteMessage({
|
|
77
|
-
fromToken: quote.fromToken,
|
|
78
|
-
toToken: quote.toToken,
|
|
79
|
-
inputAmount: quote.inputAmount,
|
|
80
|
-
outputAmount: quote.estimatedOutput,
|
|
81
|
-
}, { prefix: 'Quote:' }),
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Format a DEX pool quote response with additional pool data.
|
|
86
|
-
*
|
|
87
|
-
* Handles DexPoolQuoteResult (from calculateDexPoolQuote* methods).
|
|
88
|
-
* Includes price tracking and optionally cached data indicator.
|
|
89
|
-
*
|
|
90
|
-
* @param quote - The pool quote result to format (DexPoolQuoteResult)
|
|
91
|
-
* @param tokens - Tuple of [fromToken, toToken] symbols
|
|
92
|
-
* @param mode - Calculation mode ('local' or 'external')
|
|
93
|
-
* @param usedCachedData - Whether cached pool data was used (optional)
|
|
94
|
-
* @returns Formatted response object with pool quote fields
|
|
95
|
-
*/
|
|
96
|
-
function formatDexPoolQuoteResponse(quote, tokens, mode, usedCachedData) {
|
|
97
|
-
const [fromToken, toToken] = tokens;
|
|
98
|
-
const modeLabel = mode === 'local' ? 'Local' : 'External';
|
|
99
|
-
return {
|
|
100
|
-
mode,
|
|
101
|
-
fromToken,
|
|
102
|
-
toToken,
|
|
103
|
-
inputAmount: quote.amount0,
|
|
104
|
-
outputAmount: quote.amount1,
|
|
105
|
-
currentSqrtPrice: quote.currentSqrtPrice,
|
|
106
|
-
newSqrtPrice: quote.newSqrtPrice,
|
|
107
|
-
priceImpact: quote.priceImpact,
|
|
108
|
-
executionPrice: quote.executionPrice,
|
|
109
|
-
...(usedCachedData !== undefined && { usedCachedData }),
|
|
110
|
-
message: buildQuoteMessage({ fromToken, toToken, inputAmount: quote.amount0, outputAmount: quote.amount1 }, { prefix: `${modeLabel} quote:`, suffix: usedCachedData ? ' (using cached pool data)' : '' }),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Format a single liquidity position for MCP response.
|
|
115
|
-
*
|
|
116
|
-
* Core formatting function used by all position-related tools.
|
|
117
|
-
* Extracts and maps position fields consistently with optional metadata.
|
|
118
|
-
*
|
|
119
|
-
* @param position - SDK position object (LiquidityPosition)
|
|
120
|
-
* @param options - Optional formatting options (includeOwner, includeTimestamps)
|
|
121
|
-
* @returns Formatted position object with standardized fields
|
|
122
|
-
*
|
|
123
|
-
* @example
|
|
124
|
-
* // Basic formatting (for list responses)
|
|
125
|
-
* formatPosition(pos);
|
|
126
|
-
*
|
|
127
|
-
* // With metadata (for detail responses)
|
|
128
|
-
* formatPosition(pos, { includeOwner: true, includeTimestamps: true });
|
|
129
|
-
*/
|
|
130
|
-
function formatPosition(position, options = {}) {
|
|
131
|
-
const result = {
|
|
132
|
-
positionId: position.positionId,
|
|
133
|
-
token0: position.token0,
|
|
134
|
-
token1: position.token1,
|
|
135
|
-
feeTier: position.feeTier,
|
|
136
|
-
liquidity: String(position.liquidity),
|
|
137
|
-
tickLower: position.tickLower,
|
|
138
|
-
tickUpper: position.tickUpper,
|
|
139
|
-
};
|
|
140
|
-
// Only assign optional string properties if they have a value
|
|
141
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime defensive check for falsy values
|
|
142
|
-
if (position.amount0 !== undefined && position.amount0 !== '') {
|
|
143
|
-
result.amount0 = String(position.amount0);
|
|
144
|
-
}
|
|
145
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime defensive check for falsy values
|
|
146
|
-
if (position.amount1 !== undefined && position.amount1 !== '') {
|
|
147
|
-
result.amount1 = String(position.amount1);
|
|
148
|
-
}
|
|
149
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime defensive check for falsy values
|
|
150
|
-
if (position.feeAmount0 !== undefined && position.feeAmount0 !== '') {
|
|
151
|
-
result.feeAmount0 = String(position.feeAmount0);
|
|
152
|
-
}
|
|
153
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime defensive check for falsy values
|
|
154
|
-
if (position.feeAmount1 !== undefined && position.feeAmount1 !== '') {
|
|
155
|
-
result.feeAmount1 = String(position.feeAmount1);
|
|
156
|
-
}
|
|
157
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime defensive check for falsy values
|
|
158
|
-
if (options.includeOwner && position.ownerAddress !== undefined && position.ownerAddress !== '') {
|
|
159
|
-
result.ownerAddress = position.ownerAddress;
|
|
160
|
-
}
|
|
161
|
-
if (options.includeTimestamps) {
|
|
162
|
-
if (position.createdAt) {
|
|
163
|
-
result.createdAt = position.createdAt.toISOString();
|
|
164
|
-
}
|
|
165
|
-
if (position.updatedAt) {
|
|
166
|
-
result.updatedAt = position.updatedAt.toISOString();
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return result;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Format liquidity position data for MCP response.
|
|
173
|
-
*
|
|
174
|
-
* Convenience wrapper around formatPosition for array mapping.
|
|
175
|
-
* Handles null/undefined positions gracefully.
|
|
176
|
-
*
|
|
177
|
-
* @param positions - Array of position objects (LiquidityPosition) to format
|
|
178
|
-
* @param options - Optional formatting options passed to each position
|
|
179
|
-
* @returns Formatted positions array with standardized fields
|
|
180
|
-
*/
|
|
181
|
-
function formatPositions(positions, options = {}) {
|
|
182
|
-
return Array.isArray(positions)
|
|
183
|
-
? positions.map((pos) => formatPosition(pos, options))
|
|
184
|
-
: [];
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Validate that a wallet is configured.
|
|
188
|
-
*
|
|
189
|
-
* Checks if SDK has a valid wallet address configured by attempting to get address.
|
|
190
|
-
* Used before wallet-required operations.
|
|
191
|
-
*
|
|
192
|
-
* @param sdk - LaunchpadSDK instance
|
|
193
|
-
* @throws Error if wallet not configured
|
|
194
|
-
*/
|
|
195
|
-
function validateWalletConfigured(sdk) {
|
|
196
|
-
try {
|
|
197
|
-
sdk.getAddress();
|
|
198
|
-
}
|
|
199
|
-
catch {
|
|
200
|
-
throw new Error('Wallet not configured - required for this operation');
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Format volume trend analysis.
|
|
205
|
-
*
|
|
206
|
-
* Extracts trend direction and percentage change for volume metrics.
|
|
207
|
-
* Used for consistent volume summary formatting across tools.
|
|
208
|
-
*
|
|
209
|
-
* @param volume1d - 1-day volume
|
|
210
|
-
* @param volume7d - 7-day volume
|
|
211
|
-
* @param volume30d - 30-day volume
|
|
212
|
-
* @param delta1d - 1-day delta change value
|
|
213
|
-
* @param delta7d - 7-day delta change value
|
|
214
|
-
* @param delta30d - 30-day delta change value
|
|
215
|
-
* @returns Formatted trend analysis object
|
|
216
|
-
*/
|
|
217
|
-
function formatVolumeTrends(volume1d, volume7d, volume30d, delta1d, delta7d, delta30d) {
|
|
218
|
-
return {
|
|
219
|
-
analysis: {
|
|
220
|
-
volume1dTrend: delta1d > 0 ? 'increasing' : 'decreasing',
|
|
221
|
-
volume7dTrend: delta7d > 0 ? 'increasing' : 'decreasing',
|
|
222
|
-
volume30dTrend: delta30d > 0 ? 'increasing' : 'decreasing',
|
|
223
|
-
volume1dChangePercent: `${(delta1d * 100).toFixed(2)}%`,
|
|
224
|
-
volume7dChangePercent: `${(delta7d * 100).toFixed(2)}%`,
|
|
225
|
-
volume30dChangePercent: `${(delta30d * 100).toFixed(2)}%`,
|
|
226
|
-
},
|
|
227
|
-
formattedMetrics: {
|
|
228
|
-
volume1d: `$${volume1d.toLocaleString('en-US', { maximumFractionDigits: 2 })}`,
|
|
229
|
-
volume7d: `$${volume7d.toLocaleString('en-US', { maximumFractionDigits: 2 })}`,
|
|
230
|
-
volume30d: `$${volume30d.toLocaleString('en-US', { maximumFractionDigits: 2 })}`,
|
|
231
|
-
},
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Map token asset fields for consistent asset formatting.
|
|
236
|
-
*
|
|
237
|
-
* Extracts and formats token asset metadata with rich information.
|
|
238
|
-
* Used for consistent asset mapping across multiple tools.
|
|
239
|
-
*
|
|
240
|
-
* @param assets - Array of asset objects to map
|
|
241
|
-
* @returns Formatted assets array with standardized fields
|
|
242
|
-
*/
|
|
243
|
-
function mapTokenAssets(assets) {
|
|
244
|
-
return (Array.isArray(assets) ? assets : []).map((asset) => {
|
|
245
|
-
const result = {
|
|
246
|
-
symbol: asset.symbol,
|
|
247
|
-
balance: String(asset.balance),
|
|
248
|
-
decimals: asset.decimals,
|
|
249
|
-
};
|
|
250
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime defensive check for null/undefined
|
|
251
|
-
if (asset.name !== undefined && asset.name !== null) {
|
|
252
|
-
result.name = asset.name;
|
|
253
|
-
}
|
|
254
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime defensive check for null/undefined
|
|
255
|
-
if (asset.imageUrl !== undefined && asset.imageUrl !== null) {
|
|
256
|
-
result.image = asset.imageUrl;
|
|
257
|
-
}
|
|
258
|
-
if (typeof asset.tokenId === 'string') {
|
|
259
|
-
result.compositeKey = asset.tokenId;
|
|
260
|
-
}
|
|
261
|
-
return result;
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
// =============================================================================
|
|
265
|
-
// Fee Tier Formatting Helpers - Consistent percentage display
|
|
266
|
-
// =============================================================================
|
|
267
|
-
/**
|
|
268
|
-
* Valid GalaSwap fee tiers in basis points.
|
|
269
|
-
* Used for validation and display formatting.
|
|
270
|
-
*/
|
|
271
|
-
exports.VALID_FEE_TIERS = [500, 3000, 10000];
|
|
272
|
-
/**
|
|
273
|
-
* Format a fee tier as a percentage string.
|
|
274
|
-
*
|
|
275
|
-
* Converts basis points to percentage for human-readable display.
|
|
276
|
-
* Uses proper formula: fee / 10000 to get decimal, then format as percentage.
|
|
277
|
-
*
|
|
278
|
-
* @param fee - Fee tier in basis points (500, 3000, or 10000)
|
|
279
|
-
* @returns Formatted percentage string (e.g., "0.05%", "0.30%", "1.00%")
|
|
280
|
-
*
|
|
281
|
-
* @example
|
|
282
|
-
* formatFeeTierPercent(500) // "0.05%"
|
|
283
|
-
* formatFeeTierPercent(3000) // "0.30%"
|
|
284
|
-
* formatFeeTierPercent(10000) // "1.00%"
|
|
285
|
-
*/
|
|
286
|
-
function formatFeeTierPercent(fee) {
|
|
287
|
-
const percent = fee / 10000;
|
|
288
|
-
return `${percent.toFixed(2)}%`;
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* Format an array of fee tiers as percentage strings.
|
|
292
|
-
*
|
|
293
|
-
* Convenience wrapper for formatting multiple fee tiers.
|
|
294
|
-
* Common use case: pool info response with available fee tiers.
|
|
295
|
-
*
|
|
296
|
-
* @param tiers - Array of fee tiers in basis points
|
|
297
|
-
* @returns Array of formatted percentage strings
|
|
298
|
-
*
|
|
299
|
-
* @example
|
|
300
|
-
* formatFeeTiersPercent([500, 3000, 10000])
|
|
301
|
-
* // ["0.05%", "0.30%", "1.00%"]
|
|
302
|
-
*/
|
|
303
|
-
function formatFeeTiersPercent(tiers) {
|
|
304
|
-
return tiers.map(formatFeeTierPercent);
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Validate that a fee tier is valid.
|
|
308
|
-
*
|
|
309
|
-
* Checks if the provided fee tier is one of the valid GalaSwap fee tiers.
|
|
310
|
-
* Throws an error with helpful message if invalid.
|
|
311
|
-
*
|
|
312
|
-
* @param fee - Fee tier to validate
|
|
313
|
-
* @throws Error if fee tier is not 500, 3000, or 10000
|
|
314
|
-
*
|
|
315
|
-
* @example
|
|
316
|
-
* validateFeeTier(3000); // OK
|
|
317
|
-
* validateFeeTier(1000); // throws Error
|
|
318
|
-
*/
|
|
319
|
-
function validateFeeTier(fee) {
|
|
320
|
-
// Type guard: ensure fee is actually a number before validation
|
|
321
|
-
if (typeof fee !== 'number' || !Number.isFinite(fee)) {
|
|
322
|
-
throw new Error(`Invalid fee tier type: expected number, got ${typeof fee}. ` +
|
|
323
|
-
`Valid fee tiers are: ${exports.VALID_FEE_TIERS.join(', ')} (representing 0.05%, 0.30%, 1.00%)`);
|
|
324
|
-
}
|
|
325
|
-
if (!exports.VALID_FEE_TIERS.includes(fee)) {
|
|
326
|
-
throw new Error(`Invalid fee tier: ${fee}. Valid fee tiers are: ${exports.VALID_FEE_TIERS.join(', ')} (representing 0.05%, 0.30%, 1.00%)`);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Extract token pair parameters (token0, token1, fee) from MCP args.
|
|
331
|
-
*
|
|
332
|
-
* Eliminates repetitive type casting across DEX tools.
|
|
333
|
-
* Used in pool queries, quotes, and liquidity operations.
|
|
334
|
-
*
|
|
335
|
-
* @param args - MCP tool args object
|
|
336
|
-
* @returns Typed token pair parameters
|
|
337
|
-
*
|
|
338
|
-
* @example
|
|
339
|
-
* const { token0, token1, fee } = extractTokenPairParams(args);
|
|
340
|
-
* await sdk.fetchCompositePoolData({ token0, token1, fee });
|
|
341
|
-
*/
|
|
342
21
|
function extractTokenPairParams(args) {
|
|
343
22
|
return {
|
|
344
|
-
token0: args
|
|
345
|
-
token1: args
|
|
346
|
-
fee: args
|
|
23
|
+
token0: requiredString(args, 'token0'),
|
|
24
|
+
token1: requiredString(args, 'token1'),
|
|
25
|
+
fee: requiredNumber(args, 'fee'),
|
|
347
26
|
};
|
|
348
27
|
}
|
|
349
|
-
/**
|
|
350
|
-
* Extract token pair with tick range parameters from MCP args.
|
|
351
|
-
*
|
|
352
|
-
* Extends extractTokenPairParams with tick boundaries for concentrated liquidity.
|
|
353
|
-
* Used in position queries, liquidity add/remove, and fee estimation.
|
|
354
|
-
*
|
|
355
|
-
* @param args - MCP tool args object
|
|
356
|
-
* @returns Typed token pair with tick parameters
|
|
357
|
-
*
|
|
358
|
-
* @example
|
|
359
|
-
* const params = extractTokenPairWithTicksParams(args);
|
|
360
|
-
* await sdk.getSwapLiquidityPosition(owner, params);
|
|
361
|
-
*/
|
|
362
28
|
function extractTokenPairWithTicksParams(args) {
|
|
363
29
|
return {
|
|
364
30
|
...extractTokenPairParams(args),
|
|
365
|
-
tickLower: args
|
|
366
|
-
tickUpper: args
|
|
31
|
+
tickLower: requiredNumber(args, 'tickLower'),
|
|
32
|
+
tickUpper: requiredNumber(args, 'tickUpper'),
|
|
367
33
|
};
|
|
368
34
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
*
|
|
375
|
-
* @param token - SDK token metadata object
|
|
376
|
-
* @returns Formatted token metadata object
|
|
377
|
-
*/
|
|
378
|
-
function mapTokenMetadata(token) {
|
|
379
|
-
return {
|
|
380
|
-
symbol: token.symbol,
|
|
381
|
-
name: token.name,
|
|
382
|
-
description: token.description,
|
|
35
|
+
function mapTokenAssets(result) {
|
|
36
|
+
if (!isRecord(result) || !Array.isArray(result.tokens)) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
return result.tokens.filter(isRecord).map((token) => ({
|
|
383
40
|
image: token.image,
|
|
41
|
+
name: token.name,
|
|
384
42
|
decimals: token.decimals,
|
|
385
|
-
verified: token.
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
collection: token.collection,
|
|
390
|
-
};
|
|
43
|
+
verified: token.verify,
|
|
44
|
+
symbol: token.symbol,
|
|
45
|
+
quantity: token.quantity,
|
|
46
|
+
}));
|
|
391
47
|
}
|
|
392
|
-
/**
|
|
393
|
-
* Map array of tokens for DEX token discovery responses.
|
|
394
|
-
*
|
|
395
|
-
* Convenience wrapper around mapTokenMetadata for array mapping.
|
|
396
|
-
*
|
|
397
|
-
* @param tokens - Array of SDK token metadata objects
|
|
398
|
-
* @returns Formatted token metadata array
|
|
399
|
-
*
|
|
400
|
-
* @example
|
|
401
|
-
* const tokens = await sdk.fetchAllAvailableDexTokens({ search });
|
|
402
|
-
* return formatSuccess({ tokens: mapTokenMetadataArray(tokens) });
|
|
403
|
-
*/
|
|
404
48
|
function mapTokenMetadataArray(tokens) {
|
|
405
|
-
return
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
* @returns Normalized result with positions, prices map, and count
|
|
415
|
-
*
|
|
416
|
-
* @example
|
|
417
|
-
* const { positions, prices, pricesCount } = parsePositionListResult(result);
|
|
418
|
-
*/
|
|
419
|
-
function parsePositionListResult(result) {
|
|
420
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime defensive check for union type
|
|
421
|
-
const positions = Array.isArray(result) ? result : result !== undefined && 'items' in result ? (Array.isArray(result.items) ? result.items : []) : [];
|
|
422
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime defensive check for union type
|
|
423
|
-
const pricesValue = !Array.isArray(result) && result !== undefined && 'prices' in result ? result.prices : new Map();
|
|
424
|
-
const prices = pricesValue;
|
|
425
|
-
return {
|
|
426
|
-
positions,
|
|
427
|
-
prices,
|
|
428
|
-
pricesCount: prices.size,
|
|
429
|
-
};
|
|
49
|
+
return tokens.map((token) => ({
|
|
50
|
+
symbol: token.symbol,
|
|
51
|
+
decimals: token.decimals,
|
|
52
|
+
collection: token.collection,
|
|
53
|
+
category: token.category,
|
|
54
|
+
type: token.type,
|
|
55
|
+
additionalKey: token.additionalKey,
|
|
56
|
+
compositeKey: `${token.collection}|${token.category}|${token.type}|${token.additionalKey}`,
|
|
57
|
+
}));
|
|
430
58
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
*
|
|
434
|
-
* Consolidates the common response formatting logic used by both
|
|
435
|
-
* getUserLiquidityPositions and getAllUserLiquidityPositions tools.
|
|
436
|
-
*
|
|
437
|
-
* @param parsed - Parsed position list result from parsePositionListResult
|
|
438
|
-
* @param options - Formatting options (ownerAddress, withPrices, messageSuffix)
|
|
439
|
-
* @returns Formatted response object ready for formatSuccess()
|
|
440
|
-
*
|
|
441
|
-
* @example
|
|
442
|
-
* const parsed = parsePositionListResult(result);
|
|
443
|
-
* return formatSuccess(formatPositionListResponse(parsed, {
|
|
444
|
-
* ownerAddress: args.ownerAddress,
|
|
445
|
-
* withPrices: !!args.withPrices,
|
|
446
|
-
* messageSuffix: '(auto-paginated)',
|
|
447
|
-
* }));
|
|
448
|
-
*/
|
|
449
|
-
function formatPositionListResponse(parsed, options) {
|
|
450
|
-
const { positions, pricesCount } = parsed;
|
|
451
|
-
const { ownerAddress, withPrices, messageSuffix } = options;
|
|
452
|
-
const positionCount = positions.length;
|
|
453
|
-
// Build message with optional suffix
|
|
454
|
-
const suffix = messageSuffix !== undefined && messageSuffix !== '' ? ` ${messageSuffix}` : '';
|
|
455
|
-
const pricingNote = withPrices ? ` with pricing data for ${pricesCount}` : '';
|
|
456
|
-
const message = positionCount > 0
|
|
457
|
-
? `${positionCount} open positions found${suffix}${pricingNote}`
|
|
458
|
-
: 'No open positions found';
|
|
459
|
-
return {
|
|
460
|
-
ownerAddress,
|
|
461
|
-
positionCount,
|
|
462
|
-
positionsWithPricing: pricesCount,
|
|
463
|
-
positions: formatPositions(positions),
|
|
464
|
-
pricingStatus: withPrices
|
|
465
|
-
? `Pricing fetched for ${pricesCount}/${positionCount} positions`
|
|
466
|
-
: 'No pricing requested',
|
|
467
|
-
message,
|
|
468
|
-
};
|
|
59
|
+
function formatFeeTierPercent(fee) {
|
|
60
|
+
return `${(fee / 10000).toFixed(2)}%`;
|
|
469
61
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
*
|
|
473
|
-
* Consolidates the common response fields for addLiquidityByPrice and addLiquidityByTicks.
|
|
474
|
-
* Both operations return the same core fields, differing only in range representation.
|
|
475
|
-
*
|
|
476
|
-
* @param result - SDK add liquidity result
|
|
477
|
-
* @param inputArgs - Original input arguments (for fallback amounts)
|
|
478
|
-
* @param rangeField - Object with either priceRange or tickRange field
|
|
479
|
-
* @returns Formatted response object ready for formatSuccess()
|
|
480
|
-
*
|
|
481
|
-
* @example
|
|
482
|
-
* return formatSuccess(formatAddLiquidityResponse(result, typedArgs, {
|
|
483
|
-
* priceRange: `${typedArgs.minPrice} - ${typedArgs.maxPrice}`,
|
|
484
|
-
* }));
|
|
485
|
-
*/
|
|
486
|
-
function formatAddLiquidityResponse(result, inputArgs, rangeField) {
|
|
487
|
-
return {
|
|
488
|
-
transactionId: result.transactionId,
|
|
489
|
-
status: result.status,
|
|
490
|
-
token0: inputArgs.token0,
|
|
491
|
-
token1: inputArgs.token1,
|
|
492
|
-
...rangeField,
|
|
493
|
-
amount0: result.amount0 ?? inputArgs.amount0Desired,
|
|
494
|
-
amount1: result.amount1 ?? inputArgs.amount1Desired,
|
|
495
|
-
liquidity: result.liquidity,
|
|
496
|
-
positionId: result.positionId,
|
|
497
|
-
message: `Liquidity added! Position: ${result.positionId ?? result.transactionId}`,
|
|
498
|
-
};
|
|
62
|
+
function formatFeeTiersPercent(fees) {
|
|
63
|
+
return fees.map(formatFeeTierPercent);
|
|
499
64
|
}
|
|
500
|
-
/**
|
|
501
|
-
* Factory function to create swap quote tools with consistent structure.
|
|
502
|
-
*
|
|
503
|
-
* Eliminates duplication between exactInput and exactOutput quote tools.
|
|
504
|
-
* Both tools share identical schema and handler logic, differing only in
|
|
505
|
-
* the description and SDK method called.
|
|
506
|
-
*
|
|
507
|
-
* @param config - Configuration for the quote tool
|
|
508
|
-
* @returns MCPTool definition for the swap quote tool
|
|
509
|
-
*
|
|
510
|
-
* @example
|
|
511
|
-
* const exactInputTool = createSwapQuoteTool({
|
|
512
|
-
* name: 'gala_launchpad_get_swap_quote_exact_input',
|
|
513
|
-
* description: 'Get swap quote for exact input amount.',
|
|
514
|
-
* amountDescription: 'Amount of source token to spend',
|
|
515
|
-
* sdkMethod: 'getSwapQuoteExactInput',
|
|
516
|
-
* });
|
|
517
|
-
*/
|
|
65
|
+
/** Create a v6 `sdk.dex.quoting` MCP tool. */
|
|
518
66
|
function createSwapQuoteTool(config) {
|
|
519
67
|
return {
|
|
520
68
|
name: config.name,
|
|
@@ -527,75 +75,112 @@ function createSwapQuoteTool(config) {
|
|
|
527
75
|
...common_schemas_js_1.SWAP_QUOTE_INPUT_SCHEMA.amount,
|
|
528
76
|
description: config.amountDescription,
|
|
529
77
|
},
|
|
78
|
+
fee: {
|
|
79
|
+
type: 'number',
|
|
80
|
+
description: 'Optional fee tier in basis points.',
|
|
81
|
+
},
|
|
530
82
|
},
|
|
531
83
|
required: ['fromToken', 'toToken', 'amount'],
|
|
532
84
|
},
|
|
533
85
|
handler: (0, error_handler_js_1.withErrorHandling)(async (sdk, args) => {
|
|
534
|
-
const
|
|
535
|
-
|
|
86
|
+
const fromToken = requiredString(args, 'fromToken');
|
|
87
|
+
const toToken = requiredString(args, 'toToken');
|
|
88
|
+
const amount = requiredString(args, 'amount');
|
|
89
|
+
const fee = optionalNumber(args, 'fee');
|
|
90
|
+
const quote = config.exactOutput
|
|
91
|
+
? await sdk.dex.quoting.quoteExactOutput(fromToken, toToken, amount, fee)
|
|
92
|
+
: await sdk.dex.quoting.quoteExactInput(fromToken, toToken, amount, fee);
|
|
93
|
+
return (0, response_formatter_js_1.formatSuccess)({
|
|
94
|
+
...quote,
|
|
95
|
+
inputAmount: quote.amountIn,
|
|
96
|
+
estimatedOutput: quote.amountOut,
|
|
97
|
+
priceImpact: quote.priceImpact?.toString() ?? null,
|
|
98
|
+
message: `Quote: ${quote.amountIn} ${fromToken} -> ~${quote.amountOut} ${toToken}`,
|
|
99
|
+
});
|
|
536
100
|
}),
|
|
537
101
|
};
|
|
538
102
|
}
|
|
539
|
-
/**
|
|
540
|
-
* Factory function to create DEX pool quote tools.
|
|
541
|
-
*
|
|
542
|
-
* Eliminates duplication between local and external pool quote tools.
|
|
543
|
-
* Handles the composite pool data fetching and mode-specific SDK calls.
|
|
544
|
-
*
|
|
545
|
-
* @param config - Configuration for the pool quote tool
|
|
546
|
-
* @returns MCPTool definition for the DEX pool quote tool
|
|
547
|
-
*/
|
|
103
|
+
/** Create the legacy-named pool quote tool on the v6 quoting service. */
|
|
548
104
|
function createDexPoolQuoteTool(config) {
|
|
549
|
-
const properties = { ...common_schemas_js_1.DEX_POOL_QUOTE_INPUT_SCHEMA };
|
|
550
|
-
if (config.includeCachedDataParam) {
|
|
551
|
-
properties.compositePoolData = {
|
|
552
|
-
type: 'string',
|
|
553
|
-
description: 'Optional: Pre-fetched composite pool data as JSON string from gala_launchpad_fetch_composite_pool_data. If provided, skips fetch for efficiency (ideal for bulk quotes).',
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
105
|
return {
|
|
557
106
|
name: config.name,
|
|
558
107
|
description: config.description,
|
|
559
108
|
inputSchema: {
|
|
560
109
|
type: 'object',
|
|
561
|
-
properties,
|
|
110
|
+
properties: { ...common_schemas_js_1.DEX_POOL_QUOTE_INPUT_SCHEMA },
|
|
562
111
|
required: ['token0', 'token1', 'fee', 'fromToken', 'toToken', 'amount'],
|
|
563
112
|
},
|
|
564
113
|
handler: (0, error_handler_js_1.withErrorHandling)(async (sdk, args) => {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
}
|
|
578
|
-
if (!('pool' in composite) || !('tickDataMap' in composite)) {
|
|
579
|
-
throw new Error('compositePoolData must contain "pool" and "tickDataMap" properties. ' +
|
|
580
|
-
'Use gala_launchpad_fetch_composite_pool_data to get valid pool data.');
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
else {
|
|
584
|
-
composite = await sdk.fetchCompositePoolData(extractTokenPairParams(args));
|
|
585
|
-
}
|
|
586
|
-
// Calculate quote using appropriate SDK method
|
|
587
|
-
const sdkMethod = config.mode === 'local'
|
|
588
|
-
? 'calculateDexPoolQuoteExactAmountLocal'
|
|
589
|
-
: 'calculateDexPoolQuoteExactAmountExternal';
|
|
590
|
-
const quote = await sdk[sdkMethod]({
|
|
591
|
-
compositePoolData: composite,
|
|
592
|
-
fromToken: args.fromToken,
|
|
593
|
-
toToken: args.toToken,
|
|
594
|
-
amount: args.amount,
|
|
114
|
+
const fromToken = requiredString(args, 'fromToken');
|
|
115
|
+
const toToken = requiredString(args, 'toToken');
|
|
116
|
+
const amount = requiredString(args, 'amount');
|
|
117
|
+
const fee = requiredNumber(args, 'fee');
|
|
118
|
+
const quote = config.exactOutput === true
|
|
119
|
+
? await sdk.dex.quoting.quoteExactOutput(fromToken, toToken, amount, fee)
|
|
120
|
+
: await sdk.dex.quoting.quoteExactInput(fromToken, toToken, amount, fee);
|
|
121
|
+
return (0, response_formatter_js_1.formatSuccess)({
|
|
122
|
+
...quote,
|
|
123
|
+
mode: 'external',
|
|
124
|
+
pool: { token0: requiredString(args, 'token0'), token1: requiredString(args, 'token1'), fee },
|
|
125
|
+
priceImpact: quote.priceImpact?.toString() ?? null,
|
|
595
126
|
});
|
|
596
|
-
const usedCachedData = config.includeCachedDataParam && args.compositePoolData !== undefined && args.compositePoolData !== '' ? true : undefined;
|
|
597
|
-
return (0, response_formatter_js_1.formatSuccess)(formatDexPoolQuoteResponse(quote, [args.fromToken, args.toToken], config.mode, usedCachedData));
|
|
598
127
|
}),
|
|
599
128
|
};
|
|
600
129
|
}
|
|
130
|
+
function formatPosition(position) {
|
|
131
|
+
return {
|
|
132
|
+
pool: position.pool,
|
|
133
|
+
token0: position.token0Symbol,
|
|
134
|
+
token1: position.token1Symbol,
|
|
135
|
+
feeTier: position.fee,
|
|
136
|
+
liquidity: position.liquidity,
|
|
137
|
+
amount0: position.amount0,
|
|
138
|
+
amount1: position.amount1,
|
|
139
|
+
tickLower: position.tickLower,
|
|
140
|
+
tickUpper: position.tickUpper,
|
|
141
|
+
ownerAddress: position.owner,
|
|
142
|
+
inRange: position.inRange,
|
|
143
|
+
fees0: position.fees0,
|
|
144
|
+
fees1: position.fees1,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function formatPositions(positions) {
|
|
148
|
+
return positions.map(formatPosition);
|
|
149
|
+
}
|
|
150
|
+
function formatPool(pool) {
|
|
151
|
+
return { ...pool, feePercent: formatFeeTierPercent(pool.fee) };
|
|
152
|
+
}
|
|
153
|
+
function formatSlot0(slot0) {
|
|
154
|
+
return { ...slot0 };
|
|
155
|
+
}
|
|
156
|
+
async function formatDexSubmission(value) {
|
|
157
|
+
const formatted = await (0, response_formatter_js_1.formatSdkResult)(value);
|
|
158
|
+
return isRecord(formatted) ? formatted : { result: formatted };
|
|
159
|
+
}
|
|
160
|
+
function asPriceIn(value) {
|
|
161
|
+
return value;
|
|
162
|
+
}
|
|
163
|
+
function requiredString(args, name) {
|
|
164
|
+
const value = args[name];
|
|
165
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
166
|
+
throw new Error(`${name} must be a non-empty string`);
|
|
167
|
+
}
|
|
168
|
+
return value;
|
|
169
|
+
}
|
|
170
|
+
function requiredNumber(args, name) {
|
|
171
|
+
const value = args[name];
|
|
172
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
173
|
+
throw new Error(`${name} must be a finite number`);
|
|
174
|
+
}
|
|
175
|
+
return value;
|
|
176
|
+
}
|
|
177
|
+
function optionalNumber(args, name) {
|
|
178
|
+
const value = args[name];
|
|
179
|
+
if (value === undefined)
|
|
180
|
+
return undefined;
|
|
181
|
+
return requiredNumber(args, name);
|
|
182
|
+
}
|
|
183
|
+
function isRecord(value) {
|
|
184
|
+
return typeof value === 'object' && value !== null;
|
|
185
|
+
}
|
|
601
186
|
//# sourceMappingURL=helpers.js.map
|