@venly/wallet-mcp
Version:
Production-ready MCP server enabling AI agents to perform Web3 wallet operations through Venly's blockchain infrastructure. Supports 14+ networks including Ethereum, Polygon, Arbitrum, and stablecoin operations.
1,127 lines • 139 kB
JavaScript
/**
* Venly MCP Server
*
* Main MCP server implementation that provides blockchain wallet operations
* through the Model Context Protocol
*/
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js';
import { VenlyClient } from '../venly/VenlyClient.js';
import { CredentialValidator } from '../auth/CredentialValidator.js';
import winston, { format, transports } from 'winston';
import dotenv from 'dotenv';
// Load environment variables
dotenv.config();
/**
* Main Venly MCP Server class
*/
export class VenlyMCPServer {
server;
venlyClient;
logger;
tools = new Map();
environment;
constructor(environment) {
this.environment = environment;
this.logger = this.createLogger();
this.server = new Server({
name: `venly-mcp-server-${environment}`,
version: '1.0.0',
}, {
capabilities: {
tools: {},
},
});
// Initialize Venly client
this.venlyClient = new VenlyClient(environment);
// Register tools and handlers
this.registerTools();
this.setupHandlers();
this.logger.info('VenlyMCPServer initialized', { environment });
}
// ============================================================================
// Tool Registration
// ============================================================================
/**
* Register all available MCP tools
*/
registerTools() {
// Base credential schema for all tools
const baseCredentialProperties = {
venly_client_id: {
type: 'string',
description: 'Your Venly Client ID from the Developer Portal'
},
venly_client_secret: {
type: 'string',
description: 'Your Venly Client Secret from the Developer Portal'
}
};
// Wallet Management Tools
this.registerTool({
name: 'create_wallet',
description: 'Create a new blockchain wallet with specified network and configuration',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
secretType: {
type: 'string',
enum: ['ETHEREUM', 'MATIC', 'BSC', 'ARBITRUM', 'AVAX', 'BITCOIN', 'LITECOIN', 'OPTIMISM', 'BASE'],
description: 'Blockchain network for the wallet'
},
walletType: {
type: 'string',
enum: ['WHITE_LABEL', 'APPLICATION', 'IMPORTED'],
description: 'Type of wallet to create'
},
identifier: {
type: 'string',
description: 'Optional identifier for the wallet (e.g., user email)'
},
description: {
type: 'string',
description: 'Optional description for the wallet'
},
pincode: {
type: 'string',
description: 'Optional PIN code for wallet security (4-20 characters)'
}
},
required: ['venly_client_id', 'venly_client_secret', 'secretType', 'walletType']
}
});
this.registerTool({
name: 'delete_user',
description: 'Delete a user and all associated data (use with caution)',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
userId: {
type: 'string',
description: 'Unique identifier of the user to delete'
}
},
required: ['venly_client_id', 'venly_client_secret', 'userId']
}
});
this.registerTool({
name: 'list_users',
description: 'List all users with pagination and optional filtering',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
page: {
type: 'number',
description: 'Page number for pagination (default: 0)'
},
size: {
type: 'number',
description: 'Number of users per page (default: 20, max: 100)'
},
reference: {
type: 'string',
description: 'Filter by user reference'
},
includeSigningMethods: {
type: 'boolean',
description: 'Include signing method details (default: false)'
}
},
required: ['venly_client_id', 'venly_client_secret']
}
});
this.registerTool({
name: 'manage_signing_methods',
description: 'Add or manage signing methods for a user (PIN, Emergency Code, Biometric)',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
userId: {
type: 'string',
description: 'Unique identifier of the user'
},
action: {
type: 'string',
enum: ['CREATE', 'LIST'],
description: 'Action to perform: CREATE new signing method or LIST existing ones'
},
signingMethod: {
type: 'object',
properties: {
type: {
type: 'string',
enum: ['PIN', 'EMERGENCY_CODE', 'BIOMETRIC'],
description: 'Type of signing method to create'
},
value: {
type: 'string',
description: 'PIN (6 digits) or Emergency Code (25 chars, leave empty for auto-generation)'
}
},
description: 'Signing method details (required for CREATE action)'
}
},
required: ['venly_client_id', 'venly_client_secret', 'userId', 'action']
}
});
this.registerTool({
name: 'get_token_balances',
description: 'Get all token balances for a wallet with optional enriched metadata including USD prices, portfolio percentages, and token categories',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
walletId: {
type: 'string',
description: 'Unique identifier of the wallet'
},
enriched: {
type: 'boolean',
description: 'Whether to include enriched metadata (thumbnails, USD prices, portfolio percentages, categories). Default: false'
}
},
required: ['venly_client_id', 'venly_client_secret', 'walletId']
}
});
this.registerTool({
name: 'get_token_portfolio',
description: 'Get comprehensive token portfolio analysis including total USD value, category breakdown, and performance metrics',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
walletId: {
type: 'string',
description: 'Unique identifier of the wallet'
}
},
required: ['venly_client_id', 'venly_client_secret', 'walletId']
}
});
// Transaction Tools
this.registerTool({
name: 'send_transaction',
description: 'Send native tokens from one wallet to another',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
walletId: {
type: 'string',
description: 'Unique identifier of the source wallet'
},
to: {
type: 'string',
description: 'Destination wallet address (0x...)'
},
value: {
type: 'number',
description: 'Amount to send in wei (for native tokens like ETH, MATIC)'
},
secretType: {
type: 'string',
enum: ['ETHEREUM', 'MATIC', 'BSC', 'ARBITRUM', 'AVAX', 'OPTIMISM', 'BASE'],
description: 'Blockchain network for the transaction'
},
pincode: {
type: 'string',
description: 'PIN code for wallet authentication (optional, defaults to 123456 for testing)'
}
},
required: ['venly_client_id', 'venly_client_secret', 'walletId', 'to', 'value', 'secretType']
}
});
this.registerTool({
name: 'send_token',
description: 'Send ERC-20 tokens from one wallet to another',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
walletId: {
type: 'string',
description: 'Unique identifier of the source wallet'
},
to: {
type: 'string',
description: 'Destination wallet address (0x...)'
},
tokenAddress: {
type: 'string',
description: 'Contract address of the ERC-20 token (0x...)'
},
value: {
type: 'number',
description: 'Amount to send in token\'s smallest unit (e.g., for USDC with 6 decimals, 1000000 = 1 USDC)'
},
secretType: {
type: 'string',
enum: ['ETHEREUM', 'MATIC', 'BSC', 'ARBITRUM', 'AVAX', 'OPTIMISM', 'BASE'],
description: 'Blockchain network for the transaction'
},
pincode: {
type: 'string',
description: 'PIN code for wallet authentication (optional, defaults to 123456 for testing)'
}
},
required: ['venly_client_id', 'venly_client_secret', 'walletId', 'to', 'tokenAddress', 'value', 'secretType']
}
});
this.registerTool({
name: 'get_transaction',
description: 'Get details of a specific transaction by hash',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
transactionHash: {
type: 'string',
description: 'Transaction hash to look up (0x...)'
},
secretType: {
type: 'string',
enum: ['ETHEREUM', 'MATIC', 'BSC', 'ARBITRUM', 'AVAX', 'OPTIMISM', 'BASE'],
description: 'Blockchain network where the transaction occurred'
}
},
required: ['venly_client_id', 'venly_client_secret', 'transactionHash', 'secretType']
}
});
// User Management Tools
this.registerTool({
name: 'create_user',
description: 'Create a new user with optional signing method for wallet management',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
reference: {
type: 'string',
description: 'Optional reference identifier for the user (e.g., email, user ID from your system)'
},
signingMethod: {
type: 'object',
properties: {
type: {
type: 'string',
enum: ['PIN', 'EMERGENCY_CODE', 'BIOMETRIC'],
description: 'Type of signing method to create'
},
value: {
type: 'string',
description: 'PIN (6 digits) or Emergency Code (25 chars, leave empty for auto-generation)'
}
},
description: 'Optional signing method to create with the user'
}
},
required: ['venly_client_id', 'venly_client_secret']
}
});
this.registerTool({
name: 'get_user',
description: 'Get user details including signing methods and profile information',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
userId: {
type: 'string',
description: 'Unique identifier of the user'
}
},
required: ['venly_client_id', 'venly_client_secret', 'userId']
}
});
this.registerTool({
name: 'update_user',
description: 'Update user profile information and reference',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
userId: {
type: 'string',
description: 'Unique identifier of the user'
},
reference: {
type: 'string',
description: 'New reference identifier for the user'
}
},
required: ['venly_client_id', 'venly_client_secret', 'userId']
}
});
// Fiat Bridge Tools
this.registerTool({
name: 'get_exchange_rates',
description: 'Get real-time fiat/crypto conversion rates from multiple providers',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
fromCurrency: {
type: 'string',
description: 'Source currency code (USD, EUR, ETH, BTC, USDC)'
},
toCurrency: {
type: 'string',
description: 'Target currency code (USD, EUR, ETH, BTC, USDC)'
},
provider: {
type: 'string',
enum: ['TRANSAK', 'MOONPAY', 'RAMP_NETWORK'],
description: 'Optional provider filter for rates'
}
},
required: ['venly_client_id', 'venly_client_secret', 'fromCurrency', 'toCurrency']
}
});
// Webhook System Tools
this.registerTool({
name: 'setup_transaction_webhooks',
description: 'Configure real-time transaction monitoring webhooks',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
walletId: {
type: 'string',
description: 'Wallet ID to monitor (optional, will auto-detect if not provided)'
},
secretType: {
type: 'string',
enum: ['ETHEREUM', 'MATIC', 'BSC', 'ARBITRUM', 'AVAX', 'OPTIMISM', 'BASE'],
description: 'Blockchain network to monitor'
},
webhookUrl: {
type: 'string',
description: 'URL endpoint to receive webhook notifications'
},
events: {
type: 'array',
items: {
type: 'string',
enum: ['TRANSACTION_PENDING', 'TRANSACTION_CONFIRMED', 'TRANSACTION_FAILED', 'TRANSACTION_DROPPED']
},
description: 'Transaction events to monitor'
},
description: {
type: 'string',
description: 'Optional description for the webhook'
},
authType: {
type: 'string',
enum: ['NONE', 'API_KEY', 'BASIC_AUTH'],
description: 'Authentication type for webhook endpoint'
},
authValue: {
type: 'string',
description: 'Authentication value (API key or basic auth credentials)'
}
},
required: ['venly_client_id', 'venly_client_secret', 'webhookUrl', 'events']
}
});
this.registerTool({
name: 'setup_balance_webhooks',
description: 'Configure balance change notification webhooks',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
walletId: {
type: 'string',
description: 'Wallet ID to monitor (optional, will auto-detect if not provided)'
},
secretType: {
type: 'string',
enum: ['ETHEREUM', 'MATIC', 'BSC', 'ARBITRUM', 'AVAX', 'OPTIMISM', 'BASE'],
description: 'Blockchain network to monitor'
},
webhookUrl: {
type: 'string',
description: 'URL endpoint to receive webhook notifications'
},
minBalanceChange: {
type: 'number',
description: 'Minimum balance change to trigger notification'
},
percentageChange: {
type: 'number',
description: 'Percentage change threshold to trigger notification'
},
description: {
type: 'string',
description: 'Optional description for the webhook'
},
authType: {
type: 'string',
enum: ['NONE', 'API_KEY', 'BASIC_AUTH'],
description: 'Authentication type for webhook endpoint'
},
authValue: {
type: 'string',
description: 'Authentication value (API key or basic auth credentials)'
}
},
required: ['venly_client_id', 'venly_client_secret', 'webhookUrl']
}
});
this.registerTool({
name: 'setup_portfolio_webhooks',
description: 'Configure portfolio value change alert webhooks',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
walletId: {
type: 'string',
description: 'Wallet ID to monitor (optional, will auto-detect if not provided)'
},
webhookUrl: {
type: 'string',
description: 'URL endpoint to receive webhook notifications'
},
minValueChange: {
type: 'number',
description: 'Minimum USD value change to trigger notification'
},
percentageChange: {
type: 'number',
description: 'Portfolio percentage change threshold to trigger notification'
},
description: {
type: 'string',
description: 'Optional description for the webhook'
},
authType: {
type: 'string',
enum: ['NONE', 'API_KEY', 'BASIC_AUTH'],
description: 'Authentication type for webhook endpoint'
},
authValue: {
type: 'string',
description: 'Authentication value (API key or basic auth credentials)'
}
},
required: ['venly_client_id', 'venly_client_secret', 'webhookUrl']
}
});
this.registerTool({
name: 'process_webhook_events',
description: 'Process and analyze incoming webhook events',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
eventPayload: {
type: 'object',
description: 'Raw webhook event payload to process'
},
eventType: {
type: 'string',
description: 'Type of webhook event (optional, will be extracted from payload)'
},
validateSignature: {
type: 'boolean',
description: 'Whether to validate webhook signature (default: false)'
}
},
required: ['venly_client_id', 'venly_client_secret', 'eventPayload']
}
});
this.registerTool({
name: 'get_webhook_status',
description: 'Monitor webhook health and delivery status',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
webhookId: {
type: 'string',
description: 'Specific webhook ID to check status for'
},
webhookUrl: {
type: 'string',
description: 'Webhook URL to check status for'
}
},
required: ['venly_client_id', 'venly_client_secret']
}
});
this.registerTool({
name: 'create_fiat_onramp',
description: 'Generate fiat-to-crypto purchase links using Transak, MoonPay, or Ramp Network',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
walletId: {
type: 'string',
description: 'Target wallet ID for crypto deposit'
},
provider: {
type: 'string',
enum: ['TRANSAK', 'MOONPAY', 'RAMP_NETWORK'],
description: 'Fiat onramp provider'
},
fiatAmount: {
type: 'number',
description: 'Amount in fiat currency (e.g., 100 for $100)'
},
fiatCurrency: {
type: 'string',
description: 'Fiat currency code (USD, EUR, GBP)'
},
cryptoCurrency: {
type: 'string',
description: 'Target crypto currency (ETH, USDC, BTC)'
},
cryptoNetwork: {
type: 'string',
description: 'Blockchain network (ETHEREUM, MATIC, BSC)'
},
email: {
type: 'string',
description: 'User email for onramp process'
},
returnUrl: {
type: 'string',
description: 'Return URL after completion'
},
selectedCountryCode: {
type: 'string',
description: 'Country code (US, GB, DE)'
}
},
required: ['venly_client_id', 'venly_client_secret', 'walletId', 'provider']
}
});
this.registerTool({
name: 'create_fiat_offramp',
description: 'Generate crypto-to-fiat withdrawal links using Transak, MoonPay, or Ramp Network',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
walletId: {
type: 'string',
description: 'Source wallet ID for crypto withdrawal'
},
provider: {
type: 'string',
enum: ['TRANSAK', 'MOONPAY', 'RAMP_NETWORK'],
description: 'Fiat offramp provider'
},
cryptoAmount: {
type: 'number',
description: 'Amount in crypto currency (e.g., 1000000 for 1 USDC with 6 decimals)'
},
cryptoCurrency: {
type: 'string',
description: 'Source crypto currency (ETH, USDC, BTC)'
},
cryptoNetwork: {
type: 'string',
description: 'Blockchain network (ETHEREUM, MATIC, BSC)'
},
fiatCurrency: {
type: 'string',
description: 'Target fiat currency (USD, EUR, GBP)'
},
email: {
type: 'string',
description: 'User email for offramp process'
},
returnUrl: {
type: 'string',
description: 'Return URL after completion'
},
selectedCountryCode: {
type: 'string',
description: 'Country code (US, GB, DE)'
}
},
required: ['venly_client_id', 'venly_client_secret', 'walletId', 'provider']
}
});
this.registerTool({
name: 'track_fiat_transaction',
description: 'Monitor fiat conversion transaction status by provider transaction ID',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
transactionId: {
type: 'string',
description: 'Provider transaction ID to track'
},
provider: {
type: 'string',
enum: ['TRANSAK', 'MOONPAY', 'RAMP_NETWORK'],
description: 'Fiat provider that issued the transaction'
}
},
required: ['venly_client_id', 'venly_client_secret', 'transactionId', 'provider']
}
});
// Workflow Tools
this.registerTool({
name: 'create_workflow_template',
description: 'Define reusable multi-step financial workflows',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
name: { type: 'string' },
description: { type: 'string' },
category: {
type: 'string',
enum: ['PAYMENT', 'NFT_DISTRIBUTION', 'TOKEN_MANAGEMENT', 'PORTFOLIO_REBALANCING', 'CUSTOM']
},
steps: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'string' },
name: { type: 'string' },
type: {
type: 'string',
enum: ['CREATE_WALLET', 'SEND_TRANSACTION', 'SEND_TOKEN', 'CHECK_BALANCE', 'WAIT_FOR_CONFIRMATION', 'FIAT_ONRAMP', 'DELAY']
},
parameters: { type: 'object' },
dependencies: { type: 'array', items: { type: 'string' } }
},
required: ['id', 'name', 'type', 'parameters']
}
},
parameters: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
type: { type: 'string', enum: ['string', 'number', 'boolean', 'address', 'amount'] },
required: { type: 'boolean' },
defaultValue: {},
description: { type: 'string' }
},
required: ['name', 'type', 'required']
}
}
},
required: ['venly_client_id', 'venly_client_secret', 'name', 'description', 'category', 'steps']
}
});
this.registerTool({
name: 'execute_workflow',
description: 'Execute workflows with real-time monitoring',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
templateId: { type: 'string' },
parameters: { type: 'object' },
dryRun: { type: 'boolean' },
stopOnError: { type: 'boolean' },
maxRetries: { type: 'number' },
delayBetweenSteps: { type: 'number' }
},
required: ['venly_client_id', 'venly_client_secret', 'parameters']
}
});
this.registerTool({
name: 'monitor_workflow_status',
description: 'Track workflow execution progress',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
workflowExecutionId: { type: 'string' },
templateId: { type: 'string' },
includeStepDetails: { type: 'boolean' },
includeLogs: { type: 'boolean' }
},
required: ['venly_client_id', 'venly_client_secret', 'workflowExecutionId']
}
});
// Financial Data Tools
this.registerTool({
name: 'export_financial_data',
description: 'Generate standardized reports for tax/accounting',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
walletIds: { type: 'array', items: { type: 'string' } },
userId: { type: 'string' },
startDate: { type: 'string' },
endDate: { type: 'string' },
reportType: {
type: 'string',
enum: ['TAX_REPORT', 'ACCOUNTING_EXPORT', 'PORTFOLIO_SUMMARY', 'TRANSACTION_HISTORY', 'GAINS_LOSSES']
},
format: { type: 'string', enum: ['CSV', 'JSON', 'PDF', 'XLSX'] },
currency: { type: 'string', enum: ['USD', 'EUR', 'GBP'] },
taxYear: { type: 'number' },
jurisdiction: { type: 'string' },
includeMetadata: { type: 'boolean' },
includeNFTs: { type: 'boolean' },
includeStaking: { type: 'boolean' },
includeFees: { type: 'boolean' }
},
required: ['venly_client_id', 'venly_client_secret', 'reportType', 'format']
}
});
this.registerTool({
name: 'optimize_transaction_routing',
description: 'Intelligent routing across chains with cost optimization',
inputSchema: {
type: 'object',
properties: {
...baseCredentialProperties,
fromTokenSymbol: { type: 'string' },
fromTokenAddress: { type: 'string' },
fromTokenAmount: { type: 'number' },
fromTokenDecimals: { type: 'number' },
toTokenSymbol: { type: 'string' },
toTokenAddress: { type: 'string' },
targetAmount: { type: 'number' },
fromNetwork: { type: 'string', enum: ['ETHEREUM', 'MATIC', 'BSC', 'ARBITRUM', 'OPTIMISM', 'AVALANCHE'] },
toNetwork: { type: 'string', enum: ['ETHEREUM', 'MATIC', 'BSC', 'ARBITRUM', 'OPTIMISM', 'AVALANCHE'] },
fromWalletId: { type: 'string' },
toWalletId: { type: 'string' },
slippageTolerance: { type: 'number' },
maxHops: { type: 'number' },
prioritizeSpeed: { type: 'boolean' },
prioritizeCost: { type: 'boolean' },
prioritizeSecurity: { type: 'boolean' },
excludeDEXs: { type: 'array', items: { type: 'string' } },
preferredDEXs: { type: 'array', items: { type: 'string' } },
deadline: { type: 'number' },
enableMEVProtection: { type: 'boolean' }
},
required: ['venly_client_id', 'venly_client_secret', 'fromTokenSymbol', 'fromTokenAmount', 'toTokenSymbol', 'fromNetwork', 'toNetwork', 'fromWalletId']
}
});
this.logger.info(`Registered ${this.tools.size} MCP tools`);
}
/**
* Register a single MCP tool
*/
registerTool(tool) {
this.tools.set(tool.name, tool);
this.logger.debug(`Registered tool: ${tool.name}`);
}
// ============================================================================
// MCP Handlers Setup
// ============================================================================
/**
* Setup MCP request handlers
*/
setupHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: Array.from(this.tools.values())
}));
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
this.logger.info(`🚀 Calling MCP tool handler: ${name}`);
const result = await this.handleToolCall(name, args || {});
this.logger.info(`✅ MCP tool ${name} completed successfully`);
return result;
}
catch (error) {
this.logger.error(`❌ MCP tool error: ${name}`, {
error: error instanceof Error ? error.message : error,
requestData: {
hasClientId: !!args?.['venly_client_id'],
hasClientSecret: !!args?.['venly_client_secret'],
toolName: name
},
stack: error instanceof Error ? error.stack : undefined
});
throw new McpError(ErrorCode.InternalError, `Tool execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
});
}
// ============================================================================
// Tool Implementation
// ============================================================================
/**
* Handle individual tool calls
*/
async handleToolCall(toolName, args) {
switch (toolName) {
// Wallet Management Tools
case 'create_wallet':
return this.handleCreateWallet(args);
case 'list_wallets':
return this.handleListWallets(args);
case 'get_wallet_info':
return this.handleGetWalletInfo(args);
case 'get_wallet_balance':
return this.handleGetWalletBalance(args);
case 'get_token_balances':
return this.handleGetTokenBalances(args);
case 'get_token_portfolio':
return this.handleGetTokenPortfolio(args);
// Transaction Tools
case 'send_transaction':
return this.handleSendTransaction(args);
case 'send_token':
return this.handleSendToken(args);
case 'get_transaction':
return this.handleGetTransaction(args);
// User Management Tools
case 'create_user':
return this.handleCreateUser(args);
case 'get_user':
return this.handleGetUser(args);
case 'update_user':
return this.handleUpdateUser(args);
case 'delete_user':
return this.handleDeleteUser(args);
case 'list_users':
return this.handleListUsers(args);
case 'manage_signing_methods':
return this.handleManageSigningMethods(args);
// Fiat Bridge Tools
case 'get_exchange_rates':
return this.handleGetExchangeRates(args);
case 'create_fiat_onramp':
return this.handleCreateFiatOnramp(args);
case 'create_fiat_offramp':
return this.handleCreateFiatOfframp(args);
case 'track_fiat_transaction':
return this.handleTrackFiatTransaction(args);
// Webhook System Tools
case 'setup_transaction_webhooks':
return this.handleSetupTransactionWebhooks(args);
case 'setup_balance_webhooks':
return this.handleSetupBalanceWebhooks(args);
case 'setup_portfolio_webhooks':
return this.handleSetupPortfolioWebhooks(args);
case 'process_webhook_events':
return this.handleProcessWebhookEvents(args);
case 'get_webhook_status':
return this.handleGetWebhookStatus(args);
// Workflow Tools
case 'create_workflow_template':
return this.handleCreateWorkflowTemplate(args);
case 'execute_workflow':
return this.handleExecuteWorkflow(args);
case 'monitor_workflow_status':
return this.handleMonitorWorkflowStatus(args);
// Financial Data Tools
case 'export_financial_data':
return this.handleExportFinancialData(args);
case 'optimize_transaction_routing':
return this.handleOptimizeTransactionRouting(args);
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
/**
* Handle create_wallet tool
*/
async handleCreateWallet(args) {
try {
const credentials = CredentialValidator.extractCredentials(args);
CredentialValidator.validateCredentials(credentials);
const createWalletParams = {
secretType: args['secretType'],
walletType: args['walletType'],
identifier: args['identifier'],
description: args['description'],
pincode: args['pincode']
};
if (!createWalletParams.secretType || !createWalletParams.walletType) {
throw new Error('secretType and walletType are required');
}
const wallet = await this.venlyClient.createWallet(credentials, createWalletParams);
if (!wallet) {
throw new Error('Failed to create wallet');
}
return {
content: [{
type: 'text',
text: JSON.stringify({
success: true,
wallet: {
id: wallet.id,
address: wallet.address,
secretType: wallet.secretType,
walletType: wallet.walletType,
identifier: wallet.identifier,
description: wallet.description,
balance: wallet.balance
},
debug: {
environment: this.environment,
timestamp: new Date().toISOString(),
toolName: 'create_wallet'
}
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: 'text',
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
errorType: error?.constructor?.name || 'UnknownError',
debug: {
environment: this.environment,
timestamp: new Date().toISOString(),
toolName: 'create_wallet'
}
}, null, 2)
}]
};
}
}
/**
* Handle list_wallets tool
*/
async handleListWallets(args) {
try {
const credentials = CredentialValidator.extractCredentials(args);
CredentialValidator.validateCredentials(credentials);
const paginationParams = {};
if (args['page'] !== undefined)
paginationParams.page = args['page'];
if (args['size'] !== undefined)
paginationParams.size = args['size'];
const wallets = await this.venlyClient.listWallets(credentials, paginationParams);
if (!wallets) {
throw new Error('Failed to retrieve wallets');
}
return {
content: [{
type: 'text',
text: JSON.stringify({
success: true,
wallets: wallets.map(wallet => ({
id: wallet.id,
address: wallet.address,
secretType: wallet.secretType,
walletType: wallet.walletType,
identifier: wallet.identifier,
description: wallet.description,
balance: wallet.balance
})),
count: wallets.length,
debug: {
environment: this.environment,
timestamp: new Date().toISOString(),
credentialsUsed: {
clientId: credentials.clientId ? credentials.clientId.substring(0, 8) + '...' : 'unknown',
serverEnvironment: this.environment
}
}
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: 'text',
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
errorType: error?.constructor?.name || 'UnknownError',
debug: {
environment: this.environment,
timestamp: new Date().toISOString(),
toolName: 'list_wallets'
}
}, null, 2)
}]
};
}
}
/**
* Handle get_wallet_info tool with auto wallet ID detection
*/
async handleGetWalletInfo(args) {
try {
const credentials = CredentialValidator.extractCredentials(args);
CredentialValidator.validateCredentials(credentials);
let walletId = args['walletId'];
// If no walletId provided or it's a test ID, get a real one from list_wallets
if (!walletId || walletId.startsWith('test-')) {
console.log('🔍 No valid walletId provided, fetching real wallet from list_wallets...');
const wallets = await this.venlyClient.listWallets(credentials, { page: 1, size: 1 });
if (wallets.length === 0) {
throw new Error('No wallets found. Please create a wallet first using create_wallet, then use the returned wallet ID directly in subsequent calls.');
}
const firstWallet = wallets[0];
if (!firstWallet) {
throw new Error('Invalid wallet data received from list_wallets');
}
walletId = firstWallet.id;
console.log(`✅ Using real wallet ID: ${walletId}`);
}
const result = await this.venlyClient.getWallet(credentials, walletId);
if (!result) {
throw new Error('Wallet not found');
}
return {
content: [{
type: 'text',
text: JSON.stringify({
success: true,
wallet: {
id: result.id,
address: result.address,
secretType: result.secretType,
walletType: result.walletType,
identifier: result.identifier,
description: result.description,
balance: result.balance,
primary: result.primary,
hasCustomPin: result.hasCustomPin,
archived: result.archived,
createdAt: result.createdAt
},
debug: {
environment: this.environment,
timestamp: new Date().toISOString(),
toolName: 'get_wallet_info',
autoDetectedWalletId: walletId !== args['walletId']
}
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: 'text',
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
errorType: error?.constructor?.name || 'UnknownError',
debug: {
environment: this.environment,
timestamp: new Date().toISOString(),
toolName: 'get_wallet_info'
}
}, null, 2)
}]
};
}
}
/**
* Handle get_wallet_balance tool w