{"version":3,"sources":["../node_modules/dotenv/package.json","../node_modules/dotenv/lib/main.js","../src/config.ts","../src/index.ts","../src/mcp/wallet/get_wallet_info_tool.ts","../src/mcp/wallet/get_account_balances_tool.ts","../src/mcp/wallet/send_xrp_tool.ts","../src/mcp/wallet/create_trustline_tool.ts","../src/mcp/wallet/get_transaction_history_tool.ts","../src/mcp/wallet/validate_address_tool.ts","../src/mcp/rwa/tokenize_asset_tool.ts","../src/mcp/rwa/get_asset_info_tool.ts","../src/mcp/rwa/send_rwa_token_tool.ts","../src/mcp/rwa/create_amm_tool.ts","../src/mcp/rwa/swap_amm_tool.ts","../src/utils/xrpl_helpers.ts","../src/mcp/rwa/add_liquidity_amm_tool.ts","../src/mcp/rwa/remove_liquidity_amm_tool.ts","../src/mcp/webapp/generate_webapp_project_tool.ts","../src/mcp/index.ts","../src/agent/index.ts"],"sourcesContent":["{\n  \"name\": \"dotenv\",\n  \"version\": \"16.5.0\",\n  \"description\": \"Loads environment variables from .env file\",\n  \"main\": \"lib/main.js\",\n  \"types\": \"lib/main.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./lib/main.d.ts\",\n      \"require\": \"./lib/main.js\",\n      \"default\": \"./lib/main.js\"\n    },\n    \"./config\": \"./config.js\",\n    \"./config.js\": \"./config.js\",\n    \"./lib/env-options\": \"./lib/env-options.js\",\n    \"./lib/env-options.js\": \"./lib/env-options.js\",\n    \"./lib/cli-options\": \"./lib/cli-options.js\",\n    \"./lib/cli-options.js\": \"./lib/cli-options.js\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"scripts\": {\n    \"dts-check\": \"tsc --project tests/types/tsconfig.json\",\n    \"lint\": \"standard\",\n    \"pretest\": \"npm run lint && npm run dts-check\",\n    \"test\": \"tap run --allow-empty-coverage --disable-coverage --timeout=60000\",\n    \"test:coverage\": \"tap run --show-full-coverage --timeout=60000 --coverage-report=lcov\",\n    \"prerelease\": \"npm test\",\n    \"release\": \"standard-version\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/motdotla/dotenv.git\"\n  },\n  \"homepage\": \"https://github.com/motdotla/dotenv#readme\",\n  \"funding\": \"https://dotenvx.com\",\n  \"keywords\": [\n    \"dotenv\",\n    \"env\",\n    \".env\",\n    \"environment\",\n    \"variables\",\n    \"config\",\n    \"settings\"\n  ],\n  \"readmeFilename\": \"README.md\",\n  \"license\": \"BSD-2-Clause\",\n  \"devDependencies\": {\n    \"@types/node\": \"^18.11.3\",\n    \"decache\": \"^4.6.2\",\n    \"sinon\": \"^14.0.1\",\n    \"standard\": \"^17.0.0\",\n    \"standard-version\": \"^9.5.0\",\n    \"tap\": \"^19.2.0\",\n    \"typescript\": \"^4.8.4\"\n  },\n  \"engines\": {\n    \"node\": \">=12\"\n  },\n  \"browser\": {\n    \"fs\": false\n  }\n}\n","const fs = require('fs')\nconst path = require('path')\nconst os = require('os')\nconst crypto = require('crypto')\nconst packageJson = require('../package.json')\n\nconst version = packageJson.version\n\nconst LINE = /(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg\n\n// Parse src into an Object\nfunction parse (src) {\n  const obj = {}\n\n  // Convert buffer to string\n  let lines = src.toString()\n\n  // Convert line breaks to same format\n  lines = lines.replace(/\\r\\n?/mg, '\\n')\n\n  let match\n  while ((match = LINE.exec(lines)) != null) {\n    const key = match[1]\n\n    // Default undefined or null to empty string\n    let value = (match[2] || '')\n\n    // Remove whitespace\n    value = value.trim()\n\n    // Check if double quoted\n    const maybeQuote = value[0]\n\n    // Remove surrounding quotes\n    value = value.replace(/^(['\"`])([\\s\\S]*)\\1$/mg, '$2')\n\n    // Expand newlines if double quoted\n    if (maybeQuote === '\"') {\n      value = value.replace(/\\\\n/g, '\\n')\n      value = value.replace(/\\\\r/g, '\\r')\n    }\n\n    // Add to object\n    obj[key] = value\n  }\n\n  return obj\n}\n\nfunction _parseVault (options) {\n  const vaultPath = _vaultPath(options)\n\n  // Parse .env.vault\n  const result = DotenvModule.configDotenv({ path: vaultPath })\n  if (!result.parsed) {\n    const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`)\n    err.code = 'MISSING_DATA'\n    throw err\n  }\n\n  // handle scenario for comma separated keys - for use with key rotation\n  // example: DOTENV_KEY=\"dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenvx.com/vault/.env.vault?environment=prod\"\n  const keys = _dotenvKey(options).split(',')\n  const length = keys.length\n\n  let decrypted\n  for (let i = 0; i < length; i++) {\n    try {\n      // Get full key\n      const key = keys[i].trim()\n\n      // Get instructions for decrypt\n      const attrs = _instructions(result, key)\n\n      // Decrypt\n      decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key)\n\n      break\n    } catch (error) {\n      // last key\n      if (i + 1 >= length) {\n        throw error\n      }\n      // try next key\n    }\n  }\n\n  // Parse decrypted .env string\n  return DotenvModule.parse(decrypted)\n}\n\nfunction _warn (message) {\n  console.log(`[dotenv@${version}][WARN] ${message}`)\n}\n\nfunction _debug (message) {\n  console.log(`[dotenv@${version}][DEBUG] ${message}`)\n}\n\nfunction _dotenvKey (options) {\n  // prioritize developer directly setting options.DOTENV_KEY\n  if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {\n    return options.DOTENV_KEY\n  }\n\n  // secondary infra already contains a DOTENV_KEY environment variable\n  if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {\n    return process.env.DOTENV_KEY\n  }\n\n  // fallback to empty string\n  return ''\n}\n\nfunction _instructions (result, dotenvKey) {\n  // Parse DOTENV_KEY. Format is a URI\n  let uri\n  try {\n    uri = new URL(dotenvKey)\n  } catch (error) {\n    if (error.code === 'ERR_INVALID_URL') {\n      const err = new Error('INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development')\n      err.code = 'INVALID_DOTENV_KEY'\n      throw err\n    }\n\n    throw error\n  }\n\n  // Get decrypt key\n  const key = uri.password\n  if (!key) {\n    const err = new Error('INVALID_DOTENV_KEY: Missing key part')\n    err.code = 'INVALID_DOTENV_KEY'\n    throw err\n  }\n\n  // Get environment\n  const environment = uri.searchParams.get('environment')\n  if (!environment) {\n    const err = new Error('INVALID_DOTENV_KEY: Missing environment part')\n    err.code = 'INVALID_DOTENV_KEY'\n    throw err\n  }\n\n  // Get ciphertext payload\n  const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`\n  const ciphertext = result.parsed[environmentKey] // DOTENV_VAULT_PRODUCTION\n  if (!ciphertext) {\n    const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`)\n    err.code = 'NOT_FOUND_DOTENV_ENVIRONMENT'\n    throw err\n  }\n\n  return { ciphertext, key }\n}\n\nfunction _vaultPath (options) {\n  let possibleVaultPath = null\n\n  if (options && options.path && options.path.length > 0) {\n    if (Array.isArray(options.path)) {\n      for (const filepath of options.path) {\n        if (fs.existsSync(filepath)) {\n          possibleVaultPath = filepath.endsWith('.vault') ? filepath : `${filepath}.vault`\n        }\n      }\n    } else {\n      possibleVaultPath = options.path.endsWith('.vault') ? options.path : `${options.path}.vault`\n    }\n  } else {\n    possibleVaultPath = path.resolve(process.cwd(), '.env.vault')\n  }\n\n  if (fs.existsSync(possibleVaultPath)) {\n    return possibleVaultPath\n  }\n\n  return null\n}\n\nfunction _resolveHome (envPath) {\n  return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath\n}\n\nfunction _configVault (options) {\n  const debug = Boolean(options && options.debug)\n  if (debug) {\n    _debug('Loading env from encrypted .env.vault')\n  }\n\n  const parsed = DotenvModule._parseVault(options)\n\n  let processEnv = process.env\n  if (options && options.processEnv != null) {\n    processEnv = options.processEnv\n  }\n\n  DotenvModule.populate(processEnv, parsed, options)\n\n  return { parsed }\n}\n\nfunction configDotenv (options) {\n  const dotenvPath = path.resolve(process.cwd(), '.env')\n  let encoding = 'utf8'\n  const debug = Boolean(options && options.debug)\n\n  if (options && options.encoding) {\n    encoding = options.encoding\n  } else {\n    if (debug) {\n      _debug('No encoding is specified. UTF-8 is used by default')\n    }\n  }\n\n  let optionPaths = [dotenvPath] // default, look for .env\n  if (options && options.path) {\n    if (!Array.isArray(options.path)) {\n      optionPaths = [_resolveHome(options.path)]\n    } else {\n      optionPaths = [] // reset default\n      for (const filepath of options.path) {\n        optionPaths.push(_resolveHome(filepath))\n      }\n    }\n  }\n\n  // Build the parsed data in a temporary object (because we need to return it).  Once we have the final\n  // parsed data, we will combine it with process.env (or options.processEnv if provided).\n  let lastError\n  const parsedAll = {}\n  for (const path of optionPaths) {\n    try {\n      // Specifying an encoding returns a string instead of a buffer\n      const parsed = DotenvModule.parse(fs.readFileSync(path, { encoding }))\n\n      DotenvModule.populate(parsedAll, parsed, options)\n    } catch (e) {\n      if (debug) {\n        _debug(`Failed to load ${path} ${e.message}`)\n      }\n      lastError = e\n    }\n  }\n\n  let processEnv = process.env\n  if (options && options.processEnv != null) {\n    processEnv = options.processEnv\n  }\n\n  DotenvModule.populate(processEnv, parsedAll, options)\n\n  if (lastError) {\n    return { parsed: parsedAll, error: lastError }\n  } else {\n    return { parsed: parsedAll }\n  }\n}\n\n// Populates process.env from .env file\nfunction config (options) {\n  // fallback to original dotenv if DOTENV_KEY is not set\n  if (_dotenvKey(options).length === 0) {\n    return DotenvModule.configDotenv(options)\n  }\n\n  const vaultPath = _vaultPath(options)\n\n  // dotenvKey exists but .env.vault file does not exist\n  if (!vaultPath) {\n    _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`)\n\n    return DotenvModule.configDotenv(options)\n  }\n\n  return DotenvModule._configVault(options)\n}\n\nfunction decrypt (encrypted, keyStr) {\n  const key = Buffer.from(keyStr.slice(-64), 'hex')\n  let ciphertext = Buffer.from(encrypted, 'base64')\n\n  const nonce = ciphertext.subarray(0, 12)\n  const authTag = ciphertext.subarray(-16)\n  ciphertext = ciphertext.subarray(12, -16)\n\n  try {\n    const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce)\n    aesgcm.setAuthTag(authTag)\n    return `${aesgcm.update(ciphertext)}${aesgcm.final()}`\n  } catch (error) {\n    const isRange = error instanceof RangeError\n    const invalidKeyLength = error.message === 'Invalid key length'\n    const decryptionFailed = error.message === 'Unsupported state or unable to authenticate data'\n\n    if (isRange || invalidKeyLength) {\n      const err = new Error('INVALID_DOTENV_KEY: It must be 64 characters long (or more)')\n      err.code = 'INVALID_DOTENV_KEY'\n      throw err\n    } else if (decryptionFailed) {\n      const err = new Error('DECRYPTION_FAILED: Please check your DOTENV_KEY')\n      err.code = 'DECRYPTION_FAILED'\n      throw err\n    } else {\n      throw error\n    }\n  }\n}\n\n// Populate process.env with parsed values\nfunction populate (processEnv, parsed, options = {}) {\n  const debug = Boolean(options && options.debug)\n  const override = Boolean(options && options.override)\n\n  if (typeof parsed !== 'object') {\n    const err = new Error('OBJECT_REQUIRED: Please check the processEnv argument being passed to populate')\n    err.code = 'OBJECT_REQUIRED'\n    throw err\n  }\n\n  // Set process.env\n  for (const key of Object.keys(parsed)) {\n    if (Object.prototype.hasOwnProperty.call(processEnv, key)) {\n      if (override === true) {\n        processEnv[key] = parsed[key]\n      }\n\n      if (debug) {\n        if (override === true) {\n          _debug(`\"${key}\" is already defined and WAS overwritten`)\n        } else {\n          _debug(`\"${key}\" is already defined and was NOT overwritten`)\n        }\n      }\n    } else {\n      processEnv[key] = parsed[key]\n    }\n  }\n}\n\nconst DotenvModule = {\n  configDotenv,\n  _configVault,\n  _parseVault,\n  config,\n  decrypt,\n  parse,\n  populate\n}\n\nmodule.exports.configDotenv = DotenvModule.configDotenv\nmodule.exports._configVault = DotenvModule._configVault\nmodule.exports._parseVault = DotenvModule._parseVault\nmodule.exports.config = DotenvModule.config\nmodule.exports.decrypt = DotenvModule.decrypt\nmodule.exports.parse = DotenvModule.parse\nmodule.exports.populate = DotenvModule.populate\n\nmodule.exports = DotenvModule\n","import * as dotenv from 'dotenv';\n\nimport { RWAConfig } from './types';\n\ndotenv.config();\n\nconst getArgs = () =>\n    process.argv.reduce((args: any, arg: any) => {\n        // long arg\n        if (arg.slice(0, 2) === \"--\") {\n            const longArg = arg.split(\"=\");\n            const longArgFlag = longArg[0].slice(2);\n            const longArgValue = longArg.length > 1 ? longArg[1] : true;\n            args[longArgFlag] = longArgValue;\n        }\n        // flags\n        else if (arg[0] === \"-\") {\n            const flags = arg.slice(1).split(\"\");\n            flags.forEach((flag: any) => {\n                args[flag] = true;\n            });\n        }\n        return args;\n    }, {});\n\nexport function getRWAConfig(): RWAConfig {\n\n    const args = getArgs();\n \n    const hasPrivateKey = !!(args?.xrpl_private_key || process.env.XRPL_PRIVATE_KEY); \n    const network = ((args?.xrpl_network || process.env.XRPL_NETWORK) || 'testnet') as 'testnet' | 'mainnet' | 'devnet';\n\n    if (!hasPrivateKey) {\n        throw new Error('XRPL_PRIVATE_KEY environment variable is required');\n    }\n\n    const servers = {\n        testnet: 'wss://s.altnet.rippletest.net:51233',\n        devnet: 'wss://s.devnet.rippletest.net:51233',\n        mainnet: 'wss://xrplcluster.com'\n    };\n\n    return {\n        privateKey: args?.xrpl_private_key || process.env.XRPL_PRIVATE_KEY,\n        network,\n        server: servers[network]\n    };\n}\n\nexport function validateEnvironment(): void {\n    try {\n        getRWAConfig();\n        console.error('✅ Environment configuration valid');\n    } catch (error) {\n        console.error('❌ Environment configuration error:', error);\n        throw error;\n    }\n}\n","#!/usr/bin/env node\n\nimport { validateEnvironment } from './config';\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { RWAMcpTools } from \"./mcp\"\nimport { RWAAgent } from './agent';\n\n/**\n * Creates an MCP server for RWA tokenization on XRPL\n */\nfunction createMcpServer(agent: RWAAgent) {\n    // Create MCP server instance\n    const server = new McpServer({\n        name: \"rwa-build\",\n        version: \"0.1.0\"\n    });\n\n    // Register all RWA tools\n    for (const [_key, tool] of Object.entries(RWAMcpTools)) {\n        server.tool(tool.name, tool.description, tool.schema, async (params: any): Promise<any> => {\n            try {\n                // Execute the handler with the params directly\n                const result = await tool.handler(agent, params);\n\n                // Format the result as MCP tool response\n                return {\n                    content: [\n                        {\n                            type: \"text\",\n                            text: JSON.stringify(result, null, 2),\n                        },\n                    ],\n                };\n            } catch (error) {\n                console.error(\"Tool execution error:\", error);\n                // Handle errors in MCP format\n                return {\n                    isError: true,\n                    content: [\n                        {\n                            type: \"text\",\n                            text: error instanceof Error\n                                ? error.message\n                                : \"Unknown error occurred\",\n                        },\n                    ],\n                };\n            }\n        });\n    }\n\n    return server;\n}\n\nasync function main() {\n    try {\n        console.error(\"🏗️ Starting RWA.build MCP Server...\");\n\n        // Validate environment before proceeding\n        validateEnvironment();\n\n        // Create RWA agent\n        const rwaAgent = new RWAAgent();\n\n        // Create and start MCP server\n        const server = createMcpServer(rwaAgent);\n        const transport = new StdioServerTransport();\n        await server.connect(transport);\n\n        console.error(\"✅ RWA.build MCP Server is running!\");\n        console.error(\"🎯 Available tools (8 functional):\");\n        \n        console.error(\"\\n📊 Core Operations:\");\n        console.error(\"   • rwa_tokenize_asset - Set up issuer account (partial)\");\n        console.error(\"   • rwa_distribute_yield - Send XRP yield payments ✅\");\n        \n        console.error(\"\\n💳 Wallet Management (6 tools - all functional):\");\n        console.error(\"   • rwa_get_wallet_info - Get wallet address and balance ✅\");\n        console.error(\"   • rwa_send_xrp - Send XRP payments ✅\");\n        console.error(\"   • rwa_create_trustline - Create trustlines for tokens ✅\");\n        console.error(\"   • rwa_get_account_balances - Check all balances ✅\");\n        console.error(\"   • rwa_get_transaction_history - View transaction history ✅\");\n        console.error(\"   • rwa_validate_address - Validate XRPL addresses ✅\");\n        \n        console.error(\"\");\n        console.error(\"💡 Try: 'Check my wallet balance and create trustline for BLD tokens'\");\n        console.error(\"💰 Try: 'Send 100 XRP yield distribution to 5 token holders'\");\n\n    } catch (error) {\n        console.error('❌ Error starting RWA.build MCP server:', error);\n        process.exit(1);\n    }\n}\n\nmain();\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\n\nexport const GetWalletInfoTool: McpTool = {\n    name: \"rwa_get_wallet_info\",\n    description: \"Get wallet address and basic account information\",\n    schema: {},\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            const walletInfo = await agent.getWalletInfo();\n            const balanceInXRP = Number(walletInfo.account_data.Balance) / 1000000;\n\n            return {\n                status: \"success\",\n                message: \"✅ Wallet information retrieved successfully\",\n                wallet_details: {\n                    address: agent.wallet.address,\n                    network: agent.network,\n                    balance: `${balanceInXRP.toFixed(6)} XRP`,\n                    balance_in_drops: walletInfo.account_data.Balance,\n                    sequence: walletInfo.account_data.Sequence,\n                    account_flags: walletInfo.account_data.Flags || 0\n                },\n                account_status: {\n                    activated: true,\n                    reserve_requirement: \"10 XRP minimum\",\n                    can_tokenize: balanceInXRP >= 10,\n                    ready_for_operations: balanceInXRP >= 1\n                },\n                recommendations: balanceInXRP < 10 \n                    ? [\n                        \"⚠️ Low XRP balance detected\",\n                        \"Fund wallet with at least 10 XRP for tokenization\",\n                        \"Reserve requirement: 10 XRP for account operations\",\n                        `Current balance: ${balanceInXRP.toFixed(6)} XRP`\n                    ]\n                    : [\n                        \"✅ Wallet has sufficient balance for operations\",\n                        \"Ready to tokenize assets\",\n                        \"Ready to create trustlines and distribute yields\"\n                    ]\n            };\n        } catch (error: any) {\n            throw new Error(`Failed to get wallet info: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\n\nexport const GetAccountBalancesTool: McpTool = {\n    name: \"rwa_get_account_balances\",\n    description: \"Get all token balances and trustlines for an account\",\n    schema: {\n        account_address: z.string()\n            .regex(/^r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n            .optional()\n            .describe(\"XRPL address to check (optional, defaults to wallet address)\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            const targetAddress = input.account_address || agent.wallet.address;\n            const isOwnWallet = targetAddress === agent.wallet.address;\n\n            // Get account info for XRP balance\n            const accountInfo = await agent.client.request({\n                command: 'account_info',\n                account: targetAddress,\n                ledger_index: 'validated'\n            });\n\n            const xrpBalance = Number(accountInfo.result.account_data.Balance) / 1000000;\n\n            // Get trustlines (token balances)\n            const trustLines = await agent.client.request({\n                command: 'account_lines',\n                account: targetAddress,\n                ledger_index: 'validated'\n            });\n\n            const tokenBalances = trustLines.result.lines.map((line: any) => ({\n                currency: line.currency,\n                issuer: line.account,\n                balance: Math.abs(Number(line.balance)), // Absolute value for holders\n                limit: line.limit,\n                quality_in: line.quality_in,\n                quality_out: line.quality_out,\n                is_frozen: line.freeze || false,\n                asset_id: `${line.currency}.${line.account}`\n            }));\n\n            const totalTokenTypes = tokenBalances.length;\n            const activeBalances = tokenBalances.filter(token => token.balance > 0);\n\n            return {\n                status: \"success\",\n                message: `✅ Account balances retrieved for ${targetAddress.substring(0, 8)}...`,\n                account_info: {\n                    address: targetAddress,\n                    network: agent.network,\n                    is_own_wallet: isOwnWallet\n                },\n                xrp_balance: {\n                    amount: `${xrpBalance.toFixed(6)} XRP`,\n                    drops: accountInfo.result.account_data.Balance,\n                    available_for_fees: xrpBalance > 10,\n                    reserve_status: xrpBalance >= 10 ? \"✅ Above reserve\" : \"⚠️ Below reserve (10 XRP)\"\n                },\n                token_balances: tokenBalances.length > 0 ? tokenBalances : [],\n                portfolio_summary: {\n                    total_trustlines: totalTokenTypes,\n                    active_balances: activeBalances.length,\n                    xrp_balance: xrpBalance,\n                    portfolio_status: activeBalances.length > 0 \n                        ? `${activeBalances.length} active token positions`\n                        : \"No token holdings\"\n                },\n                insights: [\n                    `XRP Balance: ${xrpBalance.toFixed(6)} XRP`,\n                    `Token Types: ${totalTokenTypes}`,\n                    `Active Positions: ${activeBalances.length}`,\n                    ...(isOwnWallet ? [\n                        xrpBalance < 1 ? \"⚠️ Low XRP - may need funding for transactions\" : \"✅ Sufficient XRP for operations\",\n                        totalTokenTypes === 0 ? \"💡 Create trustlines to hold RWA tokens\" : `📊 Tracking ${totalTokenTypes} different tokens`\n                    ] : [\n                        \"📋 External account analysis complete\"\n                    ])\n                ]\n            };\n        } catch (error: any) {\n            if (error.message.includes('actNotFound')) {\n                return {\n                    status: \"error\",\n                    message: \"❌ Account not found\",\n                    error_details: {\n                        address: input.account_address,\n                        issue: \"Account does not exist on XRPL\",\n                        solution: \"Check address format or fund account with minimum 10 XRP\"\n                    }\n                };\n            }\n            throw new Error(`Failed to get account balances: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\n\nexport const SendXRPTool: McpTool = {\n    name: \"rwa_send_xrp\",\n    description: \"Send XRP to another XRPL address\",\n    schema: {\n        destination: z.string()\n            .regex(/^r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n            .describe(\"Recipient's XRPL address\"),\n        amount: z.number()\n            .positive()\n            .describe(\"Amount of XRP to send\"),\n        memo: z.string()\n            .optional()\n            .describe(\"Optional memo for the transaction\"),\n        destination_tag: z.number()\n            .int()\n            .min(0)\n            .max(4294967295)\n            .optional()\n            .describe(\"Optional destination tag\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            // Check sender balance first\n            const walletInfo = await agent.getWalletInfo();\n            const currentBalance = Number(walletInfo.account_data.Balance) / 1000000;\n            const requiredAmount = input.amount + 0.000012; // Amount + fee\n\n            if (currentBalance < requiredAmount) {\n                return {\n                    status: \"error\",\n                    message: \"❌ Insufficient XRP balance\",\n                    error_details: {\n                        current_balance: `${currentBalance.toFixed(6)} XRP`,\n                        required_amount: `${requiredAmount.toFixed(6)} XRP`,\n                        shortfall: `${(requiredAmount - currentBalance).toFixed(6)} XRP`,\n                        note: \"Amount includes 0.000012 XRP transaction fee\"\n                    }\n                };\n            }\n\n            // Prepare payment transaction\n            const payment: any = {\n                TransactionType: 'Payment',\n                Account: agent.wallet.address,\n                Destination: input.destination,\n                Amount: (input.amount * 1000000).toString(), // Convert to drops\n                Fee: '12' // Standard fee in drops\n            };\n\n            // Add optional fields\n            if (input.destination_tag !== undefined) {\n                payment.DestinationTag = input.destination_tag;\n            }\n\n            if (input.memo) {\n                payment.Memos = [{\n                    Memo: {\n                        MemoData: Buffer.from(input.memo, 'utf8').toString('hex')\n                    }\n                }];\n            }\n\n            // Submit transaction\n            const result = await agent.client.submitAndWait(payment, { wallet: agent.wallet });\n\n            // Get new balance\n            const newWalletInfo = await agent.getWalletInfo();\n            const newBalance = Number(newWalletInfo.account_data.Balance) / 1000000;\n\n            return {\n                status: \"success\",\n                message: `✅ Successfully sent ${input.amount} XRP to ${input.destination.substring(0, 8)}...`,\n                transaction_details: {\n                    transaction_hash: result.result.hash,\n                    ledger_index: result.result.ledger_index,\n                    fee_paid: \"0.000012 XRP\",\n                    from_address: agent.wallet.address,\n                    to_address: input.destination,\n                    amount_sent: `${input.amount} XRP`,\n                    memo: input.memo || \"None\",\n                    destination_tag: input.destination_tag || \"None\"\n                },\n                balance_changes: {\n                    previous_balance: `${currentBalance.toFixed(6)} XRP`,\n                    new_balance: `${newBalance.toFixed(6)} XRP`,\n                    total_deducted: `${(currentBalance - newBalance).toFixed(6)} XRP`\n                }\n            };\n        } catch (error: any) {\n            if (error.message.includes('tecUNFUNDED_PAYMENT')) {\n                return {\n                    status: \"error\",\n                    message: \"❌ Payment failed - insufficient funds\",\n                    error_details: {\n                        issue: \"Account does not have enough XRP for payment + fees\",\n                        suggestion: \"Check balance and reduce payment amount\"\n                    }\n                };\n            }\n\n            if (error.message.includes('tecNO_DST')) {\n                return {\n                    status: \"error\",\n                    message: \"❌ Payment failed - destination account not found\",\n                    error_details: {\n                        issue: \"Destination account does not exist\",\n                        suggestion: \"Verify recipient address or ensure account is activated\"\n                    }\n                };\n            }\n\n            throw new Error(`Failed to send XRP: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\n\nexport const CreateTrustlineTool: McpTool = {\n    name: \"rwa_create_trustline\",\n    description: \"Create a trustline to hold RWA tokens from an issuer\",\n    schema: {\n        currency: z.string()\n            .length(3)\n            .regex(/^[A-Z0-9]{3}$/)\n            .describe(\"3-letter currency code (e.g., 'BLD', 'TBL', 'GLD')\"),\n        issuer: z.string()\n            .regex(/^r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n            .describe(\"Issuer's XRPL address\"),\n        limit: z.number()\n            .positive()\n            .optional()\n            .describe(\"Maximum amount willing to hold (optional, defaults to 1000000000)\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            // Check if trustline already exists\n            const existingLines = await agent.client.request({\n                command: 'account_lines',\n                account: agent.wallet.address,\n                ledger_index: 'validated'\n            });\n\n            const existingTrustline = existingLines.result.lines.find((line: any) => \n                line.currency === input.currency && line.account === input.issuer\n            );\n\n            if (existingTrustline) {\n                return {\n                    status: \"info\",\n                    message: `ℹ️ Trustline already exists for ${input.currency}.${input.issuer.substring(0, 8)}...`,\n                    existing_trustline: {\n                        currency: existingTrustline.currency,\n                        issuer: existingTrustline.account,\n                        current_balance: Math.abs(Number(existingTrustline.balance)),\n                        limit: existingTrustline.limit,\n                        asset_id: `${existingTrustline.currency}.${existingTrustline.account}`,\n                        status: \"Active\"\n                    },\n                    recommendation: \"Trustline is ready to receive tokens\"\n                };\n            }\n\n            // Create new trustline\n            const trustSet: any = {\n                TransactionType: 'TrustSet',\n                Account: agent.wallet.address,\n                LimitAmount: {\n                    currency: input.currency,\n                    issuer: input.issuer,\n                    value: (input.limit || 1000000000).toString()\n                },\n                Fee: '12'\n            };\n\n            const result = await agent.client.submitAndWait(trustSet, { wallet: agent.wallet });\n\n            return {\n                status: \"success\",\n                message: `✅ Trustline created for ${input.currency} tokens`,\n                trustline_details: {\n                    currency: input.currency,\n                    issuer: input.issuer,\n                    limit: input.limit || 1000000000,\n                    asset_id: `${input.currency}.${input.issuer}`,\n                    current_balance: 0,\n                    ready_to_receive: true\n                },\n                transaction_info: {\n                    transaction_hash: result.result.hash,\n                    ledger_index: result.result.ledger_index,\n                    fee_paid: \"0.000012 XRP\",\n                    network: agent.network\n                },\n                next_steps: [\n                    `Ready to receive ${input.currency} tokens from issuer`,\n                    \"Tokens can now be sent to your address\",\n                    \"Monitor balance with rwa_get_account_balances\",\n                    \"Participate in yield distributions if applicable\"\n                ],\n                investment_info: {\n                    note: `This trustline allows you to hold up to ${(input.limit || 1000000000).toLocaleString()} ${input.currency} tokens`,\n                    issuer_info: `Tokens issued by: ${input.issuer}`,\n                    risk_notice: \"Only create trustlines for assets you trust and understand\"\n                }\n            };\n        } catch (error: any) {\n            if (error.message.includes('tecNO_AUTH')) {\n                return {\n                    status: \"error\",\n                    message: \"❌ Trustline creation failed - authorization required\",\n                    error_details: {\n                        issue: \"Issuer requires authorization for trustlines\",\n                        currency: input.currency,\n                        issuer: input.issuer,\n                        solution: \"Contact the asset issuer for authorization\"\n                    }\n                };\n            }\n\n            if (error.message.includes('tecNO_LINE_INSUF_RESERVE')) {\n                return {\n                    status: \"error\",\n                    message: \"❌ Insufficient XRP reserve for trustline\",\n                    error_details: {\n                        issue: \"Each trustline requires 2 XRP reserve\",\n                        solution: \"Add more XRP to your wallet (minimum 2 XRP per trustline)\",\n                        current_currency: input.currency\n                    }\n                };\n            }\n\n            throw new Error(`Failed to create trustline: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\n\nexport const GetTransactionHistoryTool: McpTool = {\n    name: \"rwa_get_transaction_history\",\n    description: \"Get recent transaction history for an account\",\n    schema: {\n        account_address: z.string()\n            .regex(/^r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n            .optional()\n            .describe(\"XRPL address to check (optional, defaults to wallet address)\"),\n        limit: z.number()\n            .int()\n            .min(1)\n            .max(100)\n            .default(20)\n            .describe(\"Number of transactions to retrieve (max 100)\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            const targetAddress = input.account_address || agent.wallet.address;\n            const isOwnWallet = targetAddress === agent.wallet.address;\n\n            // Get transaction history\n            const transactions = await agent.client.request({\n                command: 'account_tx',\n                account: targetAddress,\n                limit: input.limit || 20,\n                ledger_index_min: -1,\n                ledger_index_max: -1\n            });\n\n            const processedTxs = transactions.result.transactions.map((tx: any) => {\n                const transaction = tx.tx;\n                const meta = tx.meta;\n                const successful = meta.TransactionResult === 'tesSUCCESS';\n                \n                // Determine transaction type and details\n                let txType = transaction.TransactionType;\n                let description = '';\n                let amount = '';\n                let counterparty = '';\n\n                switch (transaction.TransactionType) {\n                    case 'Payment':\n                        const isOutgoing = transaction.Account === targetAddress;\n                        counterparty = isOutgoing ? transaction.Destination : transaction.Account;\n                        \n                        if (typeof transaction.Amount === 'string') {\n                            // XRP payment\n                            const xrpAmount = Number(transaction.Amount) / 1000000;\n                            amount = `${xrpAmount} XRP`;\n                            description = isOutgoing ? `Sent ${amount} to ${counterparty.substring(0, 8)}...` \n                                                    : `Received ${amount} from ${counterparty.substring(0, 8)}...`;\n                        } else {\n                            // Token payment\n                            amount = `${transaction.Amount.value} ${transaction.Amount.currency}`;\n                            description = isOutgoing ? `Sent ${amount} to ${counterparty.substring(0, 8)}...`\n                                                    : `Received ${amount} from ${counterparty.substring(0, 8)}...`;\n                        }\n                        break;\n                        \n                    case 'TrustSet':\n                        const currency = transaction.LimitAmount.currency;\n                        const issuer = transaction.LimitAmount.issuer;\n                        description = `Created trustline for ${currency} (${issuer.substring(0, 8)}...)`;\n                        break;\n                        \n                    case 'OfferCreate':\n                        description = `Created trading offer`;\n                        break;\n                        \n                    case 'OfferCancel':\n                        description = `Cancelled trading offer`;\n                        break;\n                        \n                    case 'EscrowCreate':\n                        description = `Created escrow`;\n                        break;\n                        \n                    case 'EscrowFinish':\n                        description = `Released escrow`;\n                        break;\n                        \n                    default:\n                        description = `${txType} transaction`;\n                }\n\n                return {\n                    hash: transaction.hash,\n                    type: txType,\n                    description: description,\n                    amount: amount,\n                    counterparty: counterparty || 'N/A',\n                    successful: successful,\n                    fee: `${Number(transaction.Fee) / 1000000} XRP`,\n                    ledger_index: tx.ledger_index,\n                    date: new Date((transaction.date + 946684800) * 1000).toISOString(), // Ripple epoch to Unix\n                    status: successful ? '✅ Success' : '❌ Failed',\n                    result_code: meta.TransactionResult\n                };\n            });\n\n            // Calculate summary stats\n            const successfulTxs = processedTxs.filter(tx => tx.successful);\n            const failedTxs = processedTxs.filter(tx => !tx.successful);\n            const payments = processedTxs.filter(tx => tx.type === 'Payment');\n            const trustlines = processedTxs.filter(tx => tx.type === 'TrustSet');\n\n            return {\n                status: \"success\",\n                message: `✅ Retrieved ${processedTxs.length} transactions for ${targetAddress.substring(0, 8)}...`,\n                account_info: {\n                    address: targetAddress,\n                    is_own_wallet: isOwnWallet,\n                    network: agent.network\n                },\n                transaction_summary: {\n                    total_transactions: processedTxs.length,\n                    successful: successfulTxs.length,\n                    failed: failedTxs.length,\n                    payments: payments.length,\n                    trustlines_created: trustlines.length,\n                    success_rate: `${((successfulTxs.length / processedTxs.length) * 100).toFixed(1)}%`\n                },\n                transactions: processedTxs,\n                insights: [\n                    `Account has ${processedTxs.length} recent transactions`,\n                    `Success rate: ${((successfulTxs.length / processedTxs.length) * 100).toFixed(1)}%`,\n                    `Payment transactions: ${payments.length}`,\n                    `Trustlines created: ${trustlines.length}`,\n                    ...(isOwnWallet ? [\n                        failedTxs.length > 0 ? `⚠️ ${failedTxs.length} failed transactions detected` : \"✅ All recent transactions successful\"\n                    ] : [])\n                ]\n            };\n        } catch (error: any) {\n            if (error.message.includes('actNotFound')) {\n                return {\n                    status: \"error\",\n                    message: \"❌ Account not found\",\n                    error_details: {\n                        address: input.account_address,\n                        issue: \"Account does not exist on XRPL or has no transaction history\",\n                        solution: \"Verify address or check if account has been activated\"\n                    }\n                };\n            }\n            throw new Error(`Failed to get transaction history: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\n\nexport const ValidateAddressTool: McpTool = {\n    name: \"rwa_validate_address\",\n    description: \"Validate XRPL address format and check if account exists\",\n    schema: {\n        address: z.string()\n            .describe(\"XRPL address to validate\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            const address = input.address.trim();\n            \n            // Format validation\n            const xrplAddressRegex = /^r[1-9A-HJ-NP-Za-km-z]{25,34}$/;\n            const isValidFormat = xrplAddressRegex.test(address);\n            \n            if (!isValidFormat) {\n                return {\n                    status: \"invalid\",\n                    message: \"❌ Invalid XRPL address format\",\n                    validation_results: {\n                        address: address,\n                        format_valid: false,\n                        exists_on_ledger: false,\n                        issues: [\n                            \"XRPL addresses must start with 'r'\",\n                            \"Must be 25-34 characters long\",\n                            \"Can only contain base58 characters (no 0, O, I, l)\"\n                        ],\n                        examples: [\n                            \"rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH\",\n                            \"rPT1Sjq2YGrBMTttX4GZHjKu9dyfQeEBUs\"\n                        ]\n                    }\n                };\n            }\n\n            await agent.connect();\n\n            // Check if account exists on ledger\n            let accountExists = false;\n            let accountInfo: any = null;\n            let errorReason = '';\n\n            try {\n                const response = await agent.client.request({\n                    command: 'account_info',\n                    account: address,\n                    ledger_index: 'validated'\n                });\n                accountExists = true;\n                accountInfo = response.result.account_data;\n            } catch (error: any) {\n                if (error.message.includes('actNotFound')) {\n                    accountExists = false;\n                    errorReason = 'Account not activated on XRPL';\n                } else {\n                    throw error;\n                }\n            }\n\n            // Additional checks if account exists\n            let accountDetails: any = {};\n            if (accountExists && accountInfo) {\n                const balance = Number(accountInfo.Balance) / 1000000;\n                accountDetails = {\n                    balance: `${balance.toFixed(6)} XRP`,\n                    sequence: accountInfo.Sequence,\n                    flags: accountInfo.Flags || 0,\n                    activated: true,\n                    reserve_met: balance >= 10,\n                    can_receive_payments: true\n                };\n            }\n\n            return {\n                status: accountExists ? \"valid\" : \"format_valid\",\n                message: accountExists \n                    ? `✅ Valid XRPL address with active account`\n                    : `⚠️ Valid format but account not found on ledger`,\n                validation_results: {\n                    address: address,\n                    format_valid: true,\n                    exists_on_ledger: accountExists,\n                    network: agent.network,\n                    ...(accountExists ? {\n                        account_details: accountDetails\n                    } : {\n                        activation_required: true,\n                        reason: errorReason,\n                        note: \"Account needs to receive minimum 10 XRP to activate\"\n                    })\n                },\n                recommendations: accountExists ? [\n                    \"✅ Address is valid and active\",\n                    \"Safe to send payments to this address\",\n                    \"Account can receive both XRP and tokens\"\n                ] : [\n                    \"⚠️ Account not yet activated on XRPL\",\n                    \"Send minimum 10 XRP to activate this address\",\n                    \"Address format is correct\"\n                ]\n            };\n        } catch (error: any) {\n            throw new Error(`Failed to validate address: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\n\nexport const TokenizeAssetTool: McpTool = {\n    name: \"rwa_tokenize_asset\",\n    description: \"Tokenize a real-world asset on XRPL with basic compliance controls\",\n    schema: {\n        asset_type: z.enum(['real_estate', 'treasury', 'commodity', 'bond'])\n            .describe(\"Type of asset to tokenize\"),\n        asset_name: z.string()\n            .min(1)\n            .max(50)\n            .describe(\"Name of the asset (e.g., 'Manhattan Office Building')\"),\n        total_value: z.number()\n            .positive()\n            .describe(\"Total value of the asset in USD\"),\n        token_symbol: z.string()\n            .length(3)\n            .regex(/^[A-Z0-9]{3}$/)\n            .describe(\"3-letter token symbol (e.g., 'BLD', 'TBL', 'GLD')\"),\n        total_supply: z.number()\n            .positive()\n            .int()\n            .describe(\"Total number of tokens to issue\"),\n        yield_rate: z.number()\n            .min(0)\n            .max(50)\n            .optional()\n            .describe(\"Annual yield percentage (e.g., 6.5 for 6.5%)\"),\n        accredited_only: z.boolean()\n            .default(false)\n            .describe(\"Restrict to accredited investors only\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            const result = await agent.tokenizeAsset({\n                type: input.asset_type,\n                name: input.asset_name,\n                totalValue: input.total_value,\n                tokenSymbol: input.token_symbol,\n                totalSupply: input.total_supply,\n                yieldRate: input.yield_rate,\n                accreditedOnly: input.accredited_only\n            });\n\n            const pricePerToken = input.total_value / input.total_supply;\n\n            return {\n                status: result.status,\n                message: `✅ Successfully tokenized ${input.asset_name} as ${input.token_symbol}`,\n                asset_details: {\n                    name: input.asset_name,\n                    type: input.asset_type,\n                    total_value: `$${input.total_value.toLocaleString()}`,\n                    total_supply: `${input.total_supply.toLocaleString()} tokens`,\n                    price_per_token: `$${pricePerToken.toFixed(2)}`,\n                    yield_rate: input.yield_rate ? `${input.yield_rate}% annually` : 'No yield configured'\n                },\n                token_info: {\n                    token_id: result.tokenId,\n                    currency_code: result.currency,\n                    issuer_address: result.issuerAddress\n                },\n                next_steps: [\n                    \"Set up yield distribution (if income-generating asset)\",\n                    \"Create trustlines for investors\",\n                    \"Configure secondary market trading\",\n                    \"Begin investor onboarding\"\n                ],\n                compliance: {\n                    accredited_only: input.accredited_only,\n                    jurisdiction: \"US (default for MVP)\",\n                    regulatory_notes: input.accredited_only\n                        ? \"⚖️ Restricted to accredited investors under Regulation D\"\n                        : \"⚖️ Consider SEC registration requirements for public offerings\"\n                }\n            };\n        } catch (error: any) {\n            throw new Error(`Failed to tokenize asset: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\n\nexport const GetAssetInfoTool: McpTool = {\n    name: \"rwa_get_asset_info\",\n    description: \"Retrieve detailed information about a tokenized RWA asset with comprehensive balance analysis\",\n    schema: {\n        asset_id: z.string()\n            .describe(\"Asset ID in format 'CURRENCY.ISSUER'\"),\n        include_holders: z.boolean()\n            .optional()\n            .describe(\"Include detailed holder information (default: false)\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            const assetId = input.asset_id;\n            const includeHolders = input.include_holders || false;\n            \n            // Get basic asset info\n            const assetInfo = await agent.getAssetInfo(assetId);\n            \n            if (!assetInfo) {\n                return {\n                    status: \"error\",\n                    message: `Asset ${assetId} not found`,\n                    suggestion: \"Verify the asset ID format (CURRENCY.ISSUER) and ensure the asset has been tokenized\"\n                };\n            }\n\n            // Get issuer account info\n            const walletInfo = await agent.getWalletInfo();\n            \n            const [currency, issuer] = assetId.split('.');\n\n            // Get actual token supply information from XRPL\n            const supplyInfo = await agent.getActualTokenSupply(assetId);\n\n            // Get comprehensive RWA token balances for the current wallet\n            const rwaBalances = await agent.getRWATokenBalances();\n\n            // Filter for this specific asset in the wallet\n            const thisAssetBalance = rwaBalances.rwa_tokens.find(token => token.asset_id === assetId);\n\n            // Get token holders if requested\n            let holdersInfo = null;\n            if (includeHolders) {\n                const holders = await agent.getTokenHolders(assetId);\n                holdersInfo = {\n                    total_holders: holders.length,\n                    top_holders: holders.slice(0, 10), // Top 10 holders\n                    holder_distribution: {\n                        whale_holders: holders.filter(h => h.percentage >= 10).length,\n                        major_holders: holders.filter(h => h.percentage >= 1 && h.percentage < 10).length,\n                        retail_holders: holders.filter(h => h.percentage < 1).length\n                    }\n                };\n            }\n\n            return {\n                status: \"success\",\n                message: `✅ Comprehensive asset information retrieved for ${assetId}`,\n                \n                // Basic Asset Information\n                asset_details: {\n                    asset_id: assetId,\n                    asset_name: assetInfo.name,\n                    asset_type: assetInfo.type,\n                    token_symbol: assetInfo.tokenSymbol,\n                    total_value: assetInfo.totalValue ? `$${assetInfo.totalValue.toLocaleString()}` : \"Not set\",\n                    planned_supply: assetInfo.totalSupply ? `${assetInfo.totalSupply.toLocaleString()} tokens` : \"Not set\",\n                    yield_rate: assetInfo.yieldRate ? `${assetInfo.yieldRate}% annually` : \"No yield configured\",\n                    price_per_token: assetInfo.totalValue && assetInfo.totalSupply ? \n                        `$${(assetInfo.totalValue / assetInfo.totalSupply).toFixed(2)}` : \"Not calculated\"\n                },\n\n                // Live XRPL Token Supply Data (following XRPL dev portal patterns)\n                live_supply_data: {\n                    actual_total_issued: `${supplyInfo.totalIssued.toLocaleString()} tokens`,\n                    circulating_supply: `${supplyInfo.circulatingSupply.toLocaleString()} tokens`,\n                    issuer_reserve: `${supplyInfo.issuerBalance.toLocaleString()} tokens`,\n                    active_holders: supplyInfo.holderCount,\n                    supply_utilization: assetInfo.totalSupply > 0 ? \n                        `${((supplyInfo.totalIssued / assetInfo.totalSupply) * 100).toFixed(1)}%` : \"N/A\"\n                },\n\n                // Current Wallet Holdings for this Asset\n                wallet_holdings: thisAssetBalance ? {\n                    your_balance: `${thisAssetBalance.balance.toLocaleString()} ${currency}`,\n                    estimated_value: thisAssetBalance.estimated_value ? \n                        `$${thisAssetBalance.estimated_value.toLocaleString()}` : \"Not available\",\n                    ownership_percentage: supplyInfo.circulatingSupply > 0 ? \n                        `${((thisAssetBalance.balance / supplyInfo.circulatingSupply) * 100).toFixed(3)}%` : \"0%\",\n                    trustline_limit: thisAssetBalance.limit || \"No limit set\"\n                } : {\n                    your_balance: \"0 tokens\",\n                    status: \"No trustline established\",\n                    action_needed: \"Create trustline to hold this RWA token\"\n                },\n\n                // Technical XRPL Information\n                token_technical_info: {\n                    currency_code: currency,\n                    issuer_address: issuer,\n                    issuer_xrp_balance: `${Number(walletInfo.account_data.Balance) / 1000000} XRP`,\n                    account_sequence: walletInfo.account_data.Sequence,\n                    network: agent.network,\n                    ledger_flags: walletInfo.account_data.Flags,\n                    owner_count: walletInfo.account_data.OwnerCount\n                },\n\n                // RWA Portfolio Context\n                portfolio_context: {\n                    total_rwa_tokens_in_wallet: rwaBalances.rwa_tokens.filter(t => t.is_rwa_token).length,\n                    total_portfolio_value: `$${rwaBalances.total_rwa_value.toLocaleString()}`,\n                    portfolio_health: rwaBalances.portfolio_summary.portfolio_health,\n                    diversification: rwaBalances.portfolio_summary.diversification\n                },\n\n                // Trading and Liquidity Information\n                trading_info: {\n                    tradeable: \"Ready for peer-to-peer transfers\",\n                    exchange_support: \"Compatible with XRPL DEX and AMM\",\n                    minimum_trade: \"1 token (divisible to 15 decimal places)\",\n                    liquidity_status: supplyInfo.holderCount > 1 ? \"Multiple holders\" : \"Single holder\",\n                    market_depth: `${supplyInfo.holderCount} active participants`\n                },\n\n                // Compliance and Regulatory\n                compliance_status: {\n                    issuer_flags: \"Standard XRPL issuer account\",\n                    transfer_restrictions: \"Configurable via trustline flags\",\n                    regulatory_framework: \"Depends on asset type and jurisdiction\",\n                    accredited_only: assetInfo.totalValue ? \"Check asset metadata\" : \"Unknown\"\n                },\n\n                // Include holders information if requested\n                ...(holdersInfo && { token_holders: holdersInfo }),\n\n                // Useful Next Actions\n                useful_operations: [\n                    !thisAssetBalance ? \"Create trustline to hold this RWA token\" : null,\n                    \"Set up yield distribution if income-generating asset\",\n                    \"Configure trading pairs on XRPL DEX\",\n                    \"Monitor token holder analytics\",\n                    \"Generate XRPL Meta TOML file for listings\"\n                ].filter(Boolean),\n\n                // Advanced Analytics\n                analytics: {\n                    tokenization_health: {\n                        metadata_available: !!assetInfo.totalValue,\n                        supply_consistency: supplyInfo.totalIssued > 0 ? \"✅ Tokens issued\" : \"⚠️ No tokens issued\",\n                        holder_growth: supplyInfo.holderCount > 1 ? \"✅ Multiple holders\" : \"📈 Growth opportunity\",\n                        value_tracking: assetInfo.totalValue ? \"✅ Asset valued\" : \"⚠️ Needs valuation\"\n                    },\n                    market_indicators: {\n                        distribution_score: supplyInfo.holderCount > 0 ? \n                            Math.min(100, (supplyInfo.holderCount / 50) * 100).toFixed(0) + \"/100\" : \"0/100\",\n                        liquidity_score: supplyInfo.circulatingSupply > 0 ? \"Active\" : \"Dormant\",\n                        adoption_phase: supplyInfo.holderCount === 0 ? \"Pre-launch\" :\n                                       supplyInfo.holderCount < 5 ? \"Early\" :\n                                       supplyInfo.holderCount < 20 ? \"Growing\" : \"Mature\"\n                    }\n                }\n            };\n        } catch (error: any) {\n            throw new Error(`Failed to get comprehensive asset info: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\nimport { Payment } from 'xrpl';\n\nexport const SendRWATokenTool: McpTool = {\n    name: \"rwa_send_rwa_token\",\n    description: \"Send RWA tokens to another XRPL address using token format like PAT.rHJZf5qYxwH2Fnms1Uwmi61VfHqoTALgXw\",\n    schema: {\n        token_id: z.string()\n            .regex(/^[A-Z0-9]{3}\\.r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n            .describe(\"Token ID in format 'CURRENCY.ISSUER' (e.g., 'PAT.rHJZf5qYxwH2Fnms1Uwmi61VfHqoTALgXw')\"),\n        destination: z.string()\n            .regex(/^r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n            .describe(\"Recipient's XRPL address\"),\n        amount: z.number()\n            .positive()\n            .describe(\"Amount of RWA tokens to send\"),\n        destination_tag: z.number()\n            .int()\n            .min(0)\n            .max(4294967295)\n            .optional()\n            .describe(\"Optional destination tag\"),\n        memo: z.string()\n            .max(1000)\n            .optional()\n            .describe(\"Optional memo for the transaction\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            // Parse token ID to extract currency and issuer\n            const [currency, issuer] = input.token_id.split('.');\n\n            // Validate that the token exists and get metadata\n            const assetInfo = await agent.getAssetInfo(input.token_id);\n            if (!assetInfo) {\n                throw new Error(`Token ${input.token_id} not found or invalid`);\n            }\n\n            // Check sender's balance for the token\n            const balances = await agent.getRWATokenBalances();\n            const tokenBalance = balances.rwa_tokens.find(\n                token => token.currency === currency && token.issuer === issuer\n            );\n\n            if (!tokenBalance || tokenBalance.balance < input.amount) {\n                throw new Error(\n                    `Insufficient balance. Available: ${tokenBalance?.balance || 0} ${currency}, Requested: ${input.amount}`\n                );\n            }\n\n            // Validate destination address\n            try {\n                const destInfo = await agent.client.request({\n                    command: 'account_info',\n                    account: input.destination,\n                    ledger_index: 'validated'\n                });\n                \n                if (!destInfo.result.account_data) {\n                    throw new Error(`Destination address ${input.destination} does not exist`);\n                }\n            } catch (error: any) {\n                if (error.message.includes('actNotFound')) {\n                    throw new Error(`Destination address ${input.destination} does not exist or is not activated`);\n                }\n                throw error;\n            }\n\n            // Check if destination has a trustline for this token\n            let hasTrustline = false;\n            try {\n                const destLines = await agent.client.request({\n                    command: 'account_lines',\n                    account: input.destination,\n                    ledger_index: 'validated'\n                });\n\n                hasTrustline = destLines.result.lines.some(\n                    line => line.currency === currency && line.account === issuer\n                );\n            } catch (error) {\n                console.error('Could not check destination trustlines:', error);\n            }\n\n            // Prepare the payment transaction\n            const payment: Payment = {\n                TransactionType: 'Payment',\n                Account: agent.wallet.address,\n                Destination: input.destination,\n                Amount: {\n                    currency: currency,\n                    issuer: issuer,\n                    value: input.amount.toString()\n                },\n                Fee: '12'\n            };\n\n            // Add destination tag if provided\n            if (input.destination_tag !== undefined) {\n                payment.DestinationTag = input.destination_tag;\n            }\n\n            // Add memo if provided\n            if (input.memo) {\n                payment.Memos = [{\n                    Memo: {\n                        MemoType: Buffer.from('rwa_transfer', 'utf8').toString('hex').toUpperCase(),\n                        MemoData: Buffer.from(input.memo, 'utf8').toString('hex').toUpperCase()\n                    }\n                }];\n            }\n\n            // Submit the payment transaction\n            const result = await agent.client.submitAndWait(payment, { wallet: agent.wallet });\n\n            // Calculate transaction cost and token value\n            const fee = Number(payment.Fee) / 1000000; // Convert drops to XRP\n            const tokenValue = assetInfo.totalValue ? \n                (input.amount * (assetInfo.totalValue / assetInfo.totalSupply)) : 0;\n\n            // Get updated balances\n            const updatedBalances = await agent.getRWATokenBalances();\n            const updatedTokenBalance = updatedBalances.rwa_tokens.find(\n                token => token.currency === currency && token.issuer === issuer\n            );\n\n            return {\n                status: \"success\",\n                message: `✅ Successfully sent ${input.amount} ${currency} tokens to ${input.destination}`,\n                transaction_details: {\n                    hash: result.result.hash,\n                    ledger_index: result.result.ledger_index,\n                    fee_paid: `${fee} XRP`,\n                    validated: result.result.validated\n                },\n                transfer_summary: {\n                    token_id: input.token_id,\n                    currency: currency,\n                    issuer: issuer,\n                    amount_sent: input.amount,\n                    estimated_value: tokenValue > 0 ? `$${tokenValue.toLocaleString()}` : 'Not available',\n                    sender: agent.wallet.address,\n                    recipient: input.destination,\n                    destination_tag: input.destination_tag,\n                    memo: input.memo\n                },\n                balance_update: {\n                    previous_balance: tokenBalance.balance,\n                    new_balance: updatedTokenBalance?.balance || 0,\n                    remaining_tokens: updatedTokenBalance?.balance || 0\n                },\n                asset_info: {\n                    asset_name: assetInfo.name,\n                    asset_type: assetInfo.type,\n                    price_per_token: assetInfo.totalValue && assetInfo.totalSupply ? \n                        `$${(assetInfo.totalValue / assetInfo.totalSupply).toFixed(2)}` : 'Not available'\n                },\n                warnings: [\n                    ...(hasTrustline ? [] : [\"⚠️ Recipient may not have a trustline for this token\"]),\n                    ...(tokenValue === 0 ? [\"⚠️ Token valuation data not available\"] : [])\n                ],\n                next_steps: [\n                    \"Verify recipient received the tokens\",\n                    \"Check transaction status on XRPL explorer\",\n                    ...(hasTrustline ? [] : [\"Ensure recipient creates trustline for this token\"])\n                ]\n            };\n\n        } catch (error: any) {\n            throw new Error(`Failed to send RWA token: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\nimport { AMMCreate, xrpToDrops } from 'xrpl';\n\nexport const CreateAMMTool: McpTool = {\n    name: \"rwa_create_amm\",\n    description: \"Create an Automated Market Maker (AMM) for trading RWA tokens with XRP\",\n    schema: {\n        token_id: z.string()\n            .regex(/^[A-Z0-9]{3}\\.r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n            .describe(\"Token ID in format 'CURRENCY.ISSUER' (e.g., 'PAT.rHJZf5qYxwH2Fnms1Uwmi61VfHqoTALgXw')\"),\n        token_amount: z.number()\n            .positive()\n            .describe(\"Amount of RWA tokens to deposit into the AMM pool\"),\n        xrp_amount: z.number()\n            .positive()\n            .describe(\"Amount of XRP to deposit into the AMM pool (should be approximately equal value to token_amount)\"),\n        trading_fee: z.number()\n            .min(0)\n            .max(1000)\n            .default(500)\n            .describe(\"Trading fee in 1/100,000 units (500 = 0.5%, max 1000 = 1%)\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            // Parse token ID to extract currency and issuer\n            const [currency, issuer] = input.token_id.split('.');\n\n            // Validate that the user has sufficient tokens and XRP\n            const balances = await agent.getRWATokenBalances();\n            const xrpBalance = balances.xrp_balance;\n            const tokenBalance = balances.rwa_tokens.find(\n                token => token.currency === currency && token.issuer === issuer\n            );\n\n            if (!tokenBalance || tokenBalance.balance < input.token_amount) {\n                throw new Error(\n                    `Insufficient token balance. Available: ${tokenBalance?.balance || 0} ${currency}, Required: ${input.token_amount}`\n                );\n            }\n \n            // Check XRP balance (account for AMM creation cost + pool deposit + reserves)\n            const ammCreationCost = 0.2; // Current AMM creation cost\n            const totalXRPNeeded = input.xrp_amount + ammCreationCost + 10; // 10 XRP reserve buffer\n\n            if (xrpBalance < totalXRPNeeded) {\n                throw new Error(\n                    `Insufficient XRP balance. Available: ${xrpBalance} XRP, Required: ${totalXRPNeeded} XRP (includes ${ammCreationCost} XRP creation cost)`\n                );\n            }\n\n            // Check if AMM already exists for this pair\n            // try {\n            //     const existingAMM = await agent.client.request({\n            //         command: 'amm_info',\n            //         asset: {\n            //             currency: currency,\n            //             issuer: issuer\n            //         },\n            //         asset2: {\n            //             currency: \"XRP\"\n            //         }\n            //     });\n\n            //     if (existingAMM.result.amm) {\n            //         throw new Error(`AMM already exists for ${currency}/XRP pair. AMM Account: ${existingAMM.result.amm.account}`);\n            //     }\n            // } catch (error: any) {\n            //     // AMM doesn't exist, which is what we want\n            //     if (!error.message.includes('actNotFound')) {\n            //         throw error;\n            //     }\n            // }\n \n            // Get current server state to determine exact AMM creation cost\n            const serverInfo: any = await agent.client.request({\n                command: 'server_state'\n            });\n \n\n            const amm_fee_drops = serverInfo.result.state.validated_ledger!.reserve_inc.toString()\n            const actualCreationCost = amm_fee_drops\n \n\n            // Prepare the AMMCreate transaction\n            const ammCreateTx: AMMCreate = {\n                TransactionType: 'AMMCreate',\n                Account: agent.wallet.address,\n                Amount: {\n                    currency: currency,\n                    issuer: issuer,\n                    value: input.token_amount.toString()\n                },\n                Amount2: xrpToDrops(input.xrp_amount), // Convert XRP to drops\n                TradingFee: input.trading_fee,\n                Fee: actualCreationCost // Set the actual creation cost\n            };\n\n            // Submit the AMM creation transaction\n            const result: any = await agent.client.submitAndWait(ammCreateTx, {\n                wallet: agent.wallet,\n                autofill: true,\n                failHard: true\n            });\n \n            if (result.result.meta?.TransactionResult !== 'tesSUCCESS') {\n                throw new Error(`AMM creation failed: ${result.result.meta?.TransactionResult}`);\n            }\n\n            // Get the new AMM info\n            const ammInfo: any = await agent.client.request({\n                command: 'amm_info',\n                asset: {\n                    currency: currency,\n                    issuer: issuer\n                },\n                asset2: {\n                    currency: \"XRP\"\n                }\n            });\n \n\n            const amm = ammInfo.result.amm;\n            const lpTokens = amm.lp_token;\n\n            // Calculate pool metrics\n            const tokenPoolValue = parseFloat(amm.amount.value);\n            const xrpPoolValue = Number(amm.amount2) / 1000000; // Convert drops to XRP\n            const totalValueLocked = input.token_amount * 2; // Assuming equal values deposited\n            const lpTokensReceived = parseFloat(lpTokens.value);\n\n            // Get asset metadata for valuation\n            const assetInfo = await agent.getAssetInfo(input.token_id);\n            const tokenPriceUSD = assetInfo?.totalValue && assetInfo?.totalSupply ?\n                assetInfo.totalValue / assetInfo.totalSupply : 0;\n\n            return {\n                status: \"success\",\n                message: `✅ Successfully created AMM for ${currency}/XRP pair`,\n                amm_details: {\n                    amm_account: amm.account,\n                    amm_id: `${currency}/XRP`,\n                    token_pool: `${tokenPoolValue} ${currency}`,\n                    xrp_pool: `${xrpPoolValue} XRP`,\n                    trading_fee: `${input.trading_fee / 100}%`,\n                    lp_tokens_received: lpTokensReceived\n                },\n                transaction_info: {\n                    hash: result.result.hash,\n                    ledger_index: result.result.ledger_index,\n                    fee_burned: `${actualCreationCost} XRP`,\n                    validated: result.result.validated\n                },\n                pool_metrics: {\n                    initial_token_deposit: input.token_amount,\n                    initial_xrp_deposit: input.xrp_amount,\n                    estimated_pool_value_usd: tokenPriceUSD > 0 ?\n                        `$${(tokenPriceUSD * input.token_amount * 2).toLocaleString()}` : 'Not available',\n                    lp_token_symbol: lpTokens.currency,\n                    lp_token_issuer: lpTokens.issuer,\n                    your_pool_share: \"100%\" // As the creator, you own all LP tokens initially\n                },\n                trading_info: {\n                    can_trade: true,\n                    supported_pairs: [`${currency} → XRP`, `XRP → ${currency}`],\n                    current_rate: `1 ${currency} = ${(xrpPoolValue / tokenPoolValue).toFixed(6)} XRP`,\n                    slippage_tolerance: \"Automatic based on pool depth\"\n                },\n                next_steps: [\n                    \"Monitor AMM performance and trading activity\",\n                    \"Consider adding more liquidity to reduce slippage\",\n                    \"Invite other users to provide liquidity\",\n                    \"Use the AMM for token swaps\",\n                    \"Monitor LP token value and yields\"\n                ],\n                warnings: [\n                    \"⚠️ As a liquidity provider, you're exposed to impermanent loss\",\n                    \"⚠️ Token price volatility affects LP token value\",\n                    \"⚠️ Consider the trading fee vs. volatility balance\"\n                ]\n            };\n\n        } catch (error: any) {\n            throw new Error(`Failed to create AMM: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\nimport { Payment, xrpToDrops } from 'xrpl';\nimport { dropsToXrp } from \"../../utils/xrpl_helpers\";\n\nexport const SwapAMMTool: McpTool = {\n    name: \"rwa_swap_amm\",\n    description: \"Swap tokens using XRPL AMM (Automated Market Maker) - supports RWA token ↔ XRP swaps\",\n    schema: {\n        from_asset: z.union([\n            z.literal(\"XRP\"),\n            z.string().regex(/^[A-Z0-9]{3}\\.r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n        ]).describe(\"Asset to swap from: 'XRP' or token in format 'CURRENCY.ISSUER'\"),\n        to_asset: z.union([\n            z.literal(\"XRP\"),\n            z.string().regex(/^[A-Z0-9]{3}\\.r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n        ]).describe(\"Asset to swap to: 'XRP' or token in format 'CURRENCY.ISSUER'\"),\n        amount: z.number()\n            .positive()\n            .describe(\"Amount of the 'from_asset' to swap\"),\n        max_slippage_percent: z.number()\n            .min(0.1)\n            .max(50)\n            .default(2.0)\n            .describe(\"Maximum acceptable slippage percentage (default: 2%)\"),\n        memo: z.string()\n            .max(1000)\n            .optional()\n            .describe(\"Optional memo for the swap transaction\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            // Validate that we're not trying to swap the same asset\n            if (input.from_asset === input.to_asset) {\n                throw new Error(\"Cannot swap an asset to itself\");\n            }\n\n            // Parse asset information\n            let fromCurrency: string | null, fromIssuer: string | undefined;\n            let toCurrency: string | null, toIssuer: string | undefined;\n\n            if (input.from_asset === \"XRP\") {\n                fromCurrency = null; // XRP has no currency code\n                fromIssuer = undefined;\n            } else {\n                [fromCurrency, fromIssuer] = input.from_asset.split('.');\n            }\n\n            if (input.to_asset === \"XRP\") {\n                toCurrency = null; // XRP has no currency code\n                toIssuer = undefined;\n            } else {\n                [toCurrency, toIssuer] = input.to_asset.split('.');\n            }\n\n            // Check user's balance for the from_asset\n            const balances = await agent.getRWATokenBalances();\n            let fromBalance = 0;\n\n            if (input.from_asset === \"XRP\") {\n                fromBalance = balances.xrp_balance;\n                const availableXRP = fromBalance - 11; // Keep 11 XRP reserved\n                if (availableXRP < input.amount) {\n                    throw new Error(\n                        `Insufficient XRP balance. Available for swap: ${availableXRP} XRP, Requested: ${input.amount} XRP`\n                    );\n                }\n            } else {\n                const tokenBalance = balances.rwa_tokens.find(\n                    token => token.currency === fromCurrency && token.issuer === fromIssuer\n                );\n                fromBalance = tokenBalance?.balance || 0;\n\n                if (fromBalance < input.amount) {\n                    throw new Error(\n                        `Insufficient ${fromCurrency} balance. Available: ${fromBalance}, Requested: ${input.amount}`\n                    );\n                }\n            }\n\n            // Check if AMM exists for this pair\n            let ammInfo;\n            try {\n                const ammAsset1: any = input.from_asset === \"XRP\" ?\n                    { currency: \"XRP\" } :\n                    { currency: fromCurrency, issuer: fromIssuer };\n                const ammAsset2: any = input.to_asset === \"XRP\" ?\n                    { currency: \"XRP\" } :\n                    { currency: toCurrency, issuer: toIssuer };\n\n                ammInfo = await agent.client.request({\n                    command: 'amm_info',\n                    asset: ammAsset1,\n                    asset2: ammAsset2,\n                    ledger_index: \"validated\"\n                });\n            } catch (error: any) {\n                console.warn(\"AMM not found, will try order book routing\");\n            }\n\n            console.error(\"AMM exists about to swap...\", ammInfo)\n\n            // Estimate output amount with slippage protection\n            const slippageMultiplier = (100 - input.max_slippage_percent) / 100;\n            let estimatedOutput = input.amount; // Simple 1:1 estimate, will be refined by path_find\n\n            if (ammInfo?.result?.amm) {\n                const amm: any = ammInfo.result.amm;\n                const tradingFeeRate = amm.trading_fee / 100000;\n\n                if (input.from_asset === \"XRP\") { \n                    const xrpPool = Number(amm.amount) / 1000000;\n                    const tokenPool = parseFloat(amm.amount2.value);\n                    const inputAfterFee = input.amount * (1 - tradingFeeRate);\n                    estimatedOutput = (inputAfterFee * tokenPool) / (xrpPool + inputAfterFee);\n                } else { \n                    const tokenPool = parseFloat(amm.amount.value);\n                    const xrpPool = Number(amm.amount2) / 1000000;\n                    const inputAfterFee = input.amount * (1 - tradingFeeRate);\n                    estimatedOutput = (inputAfterFee * xrpPool) / (tokenPool + inputAfterFee);\n                }\n            }\n\n            const minimumOutput = estimatedOutput * slippageMultiplier;\n  \n            // Use path_find to discover optimal routing (following your example)\n            let pathFindResult: any;\n\n            try {\n                let pathFindRequest: any = {\n                    command: 'path_find',\n                    subcommand: 'create',\n                    source_account: agent.wallet.address,\n                    destination_account: agent.wallet.address\n                };\n\n                // Set source and destination amounts based on swap direction\n                if (input.from_asset === \"XRP\") {\n                    // XRP -> Token\n                    pathFindRequest.source_amount = xrpToDrops(input.amount);\n                    pathFindRequest.destination_amount = {\n                        currency: toCurrency,\n                        value: minimumOutput.toString(),\n                        issuer: toIssuer\n                    };\n                } else if (input.to_asset === \"XRP\") {\n                    // Token -> XRP\n                    pathFindRequest.source_amount = {\n                        currency: fromCurrency,\n                        value: input.amount.toString(),\n                        issuer: fromIssuer\n                    };\n                    pathFindRequest.destination_amount = xrpToDrops(minimumOutput);\n                } else {\n                    // Token -> Token\n                    pathFindRequest.source_amount = {\n                        currency: fromCurrency,\n                        value: input.amount.toString(),\n                        issuer: fromIssuer\n                    };\n                    pathFindRequest.destination_amount = {\n                        currency: toCurrency,\n                        value: minimumOutput.toString(),\n                        issuer: toIssuer\n                    };\n                }\n\n                pathFindResult = await agent.client.request(pathFindRequest);\n            } catch (error: any) {\n                console.warn(\"Path finding failed:\", error.message);\n            }\n \n\n            // Create swap transaction (following your example structure)\n            let swapTxData: any;\n\n            if (input.from_asset === \"XRP\") {\n                // XRP -> Token\n                swapTxData = {\n                    TransactionType: \"Payment\",\n                    Account: agent.wallet.address,\n                    Destination: agent.wallet.address,\n                    Amount: {\n                        currency: toCurrency!,\n                        value: minimumOutput.toString(),\n                        issuer: toIssuer!\n                    },\n                    SendMax: xrpToDrops(input.amount),\n                    Paths: [[\n                        {\n                            currency: toCurrency!,\n                            issuer: toIssuer!,\n                            type: 48\n                        }\n                    ]],\n                    Fee: '12'\n                };\n            } else if (input.to_asset === \"XRP\") {\n                // Token -> XRP\n                swapTxData = {\n                    TransactionType: \"Payment\",\n                    Account: agent.wallet.address,\n                    Destination: agent.wallet.address,\n                    Amount: xrpToDrops(minimumOutput),\n                    SendMax: {\n                        currency: fromCurrency!,\n                        value: input.amount.toString(),\n                        issuer: fromIssuer!\n                    },\n                    Paths: [[\n                        {\n                            currency: \"XRP\",\n                            type: 16\n                        }\n                    ]],\n                    Fee: '12'\n                };\n            } else {\n                // Token -> Token\n                swapTxData = {\n                    TransactionType: \"Payment\",\n                    Account: agent.wallet.address,\n                    Destination: agent.wallet.address,\n                    Amount: {\n                        currency: toCurrency!,\n                        value: minimumOutput.toString(),\n                        issuer: toIssuer!\n                    },\n                    SendMax: {\n                        currency: fromCurrency!,\n                        value: input.amount.toString(),\n                        issuer: fromIssuer!\n                    },\n                    Paths: [[\n                        {\n                            account: fromIssuer!,\n                            type: 1\n                        },\n                        {\n                            currency: toCurrency!,\n                            issuer: toIssuer!,\n                            type: 48\n                        }\n                    ]],\n                    Fee: '12'\n                };\n            }\n \n\n            // Use paths from path_find if available\n            if (pathFindResult?.result?.alternatives?.length > 0) {\n                const bestAlternative = pathFindResult.result.alternatives[0];\n                if (bestAlternative.paths_computed && bestAlternative.paths_computed.length > 0) {\n                    swapTxData.Paths = bestAlternative.paths_computed;\n                }\n            }\n\n            // Add memo if provided\n            if (input.memo) {\n                swapTxData.Memos = [{\n                    Memo: {\n                        MemoType: Buffer.from('amm_swap', 'utf8').toString('hex').toUpperCase(),\n                        MemoData: Buffer.from(input.memo, 'utf8').toString('hex').toUpperCase()\n                    }\n                }];\n            }\n\n            // Submit the transaction\n            const payPrepared = await agent.client.autofill(swapTxData);\n            const paySigned = agent.wallet.sign(payPrepared);\n            const payResult: any = await agent.client.submitAndWait(paySigned.tx_blob);\n\n            if (payResult.result.meta.TransactionResult !== \"tesSUCCESS\") {\n                throw new Error(`Swap failed: ${payResult.result.meta.TransactionResult}`);\n            }\n \n\n            // Extract actual delivered amount\n            const deliveredAmount = payResult.result.meta?.delivered_amount;\n            let actualOutputAmount: number;\n            let actualOutputDisplay: string;\n\n            if (input.to_asset === \"XRP\") {\n                actualOutputAmount = typeof deliveredAmount === 'string' ?\n                    parseFloat(`${dropsToXrp(deliveredAmount)}`) : 0;\n                actualOutputDisplay = `${actualOutputAmount} XRP`;\n            } else {\n                actualOutputAmount = typeof deliveredAmount === 'object' && deliveredAmount?.value ?\n                    parseFloat(deliveredAmount.value) : 0;\n                actualOutputDisplay = `${actualOutputAmount} ${toCurrency}`;\n            }\n\n            // Calculate metrics\n            const actualRate = actualOutputAmount / input.amount;\n            const expectedRate = estimatedOutput / input.amount;\n            const actualSlippage = expectedRate > 0 ?\n                Math.abs((expectedRate - actualRate) / expectedRate) * 100 : 0;\n\n            // Get updated balances\n            const updatedBalances = await agent.client.request({\n                command: \"account_lines\",\n                account: agent.wallet.address,\n                ledger_index: \"validated\"\n            });\n \n            return {\n                status: \"success\",\n                message: `✅ Successfully swapped ${input.amount} ${input.from_asset === \"XRP\" ? \"XRP\" : fromCurrency} for ${actualOutputDisplay}`,\n                swap_details: {\n                    from_asset: input.from_asset,\n                    to_asset: input.to_asset,\n                    input_amount: input.amount,\n                    output_amount: actualOutputAmount,\n                    output_display: actualOutputDisplay,\n                    swap_rate: `1 ${input.from_asset === \"XRP\" ? \"XRP\" : fromCurrency} = ${actualRate.toFixed(6)} ${input.to_asset === \"XRP\" ? \"XRP\" : toCurrency}`\n                },\n                transaction_info: {\n                    hash: paySigned.hash,\n                    ledger_index: payResult.result.ledger_index,\n                    fee_paid: `${Number(swapTxData.Fee) / 1000000} XRP`,\n                    validated: payResult.result.validated,\n                    transaction_result: payResult.result.meta.TransactionResult\n                },\n                execution_metrics: {\n                    expected_output: estimatedOutput.toFixed(6),\n                    minimum_expected: minimumOutput.toFixed(6),\n                    actual_output: actualOutputAmount.toFixed(6),\n                    slippage_experienced: `${actualSlippage.toFixed(3)}%`,\n                    slippage_tolerance: `${input.max_slippage_percent}%`,\n                    slippage_status: actualSlippage <= input.max_slippage_percent ?\n                        \"✅ Within tolerance\" : \"⚠️ Exceeded tolerance\"\n                },\n                routing_info: {\n                    path_finding_used: !!pathFindResult?.result?.alternatives?.length,\n                    paths_computed: pathFindResult?.result?.alternatives?.length || 0,\n                    amm_available: !!ammInfo?.result?.amm,\n                    execution_method: \"Payment with Paths\"\n                },\n                updated_balances: {\n                    account_lines: updatedBalances.result.lines,\n                    balance_count: updatedBalances.result.lines.length\n                },\n                next_steps: [\n                    \"Check your updated token balances\",\n                    \"Monitor price movements for future trades\",\n                    \"Consider providing liquidity if spreads are wide\"\n                ]\n            };\n\n        } catch (error: any) {\n            throw new Error(`Failed to swap on AMM: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { convertStringToHex, convertHexToString } from 'xrpl';\nimport { Wallet } from \"xrpl\"\n\nexport function generateCurrencyCode(tokenSymbol: string): string {\n    // Ensure 3 characters, uppercase\n    return tokenSymbol.toUpperCase().padEnd(3, '0').substring(0, 3);\n}\n\nexport function formatCurrencyCode(currency: string): string {\n    // Remove trailing zeros and format for display\n    return currency.replace(/0+$/, '');\n}\n\nexport function createMemo(text: string): any {\n    return {\n        Memo: {\n            MemoData: convertStringToHex(text)\n        }\n    };\n}\n\nexport function parseMemo(memoData: string): string {\n    try {\n        return convertHexToString(memoData);\n    } catch (error) {\n        return memoData; // Return as-is if conversion fails\n    }\n}\n\nexport function generateAssetId(currencyCode: string, issuerAddress: string): string {\n    return `${currencyCode}.${issuerAddress}`;\n}\n\nexport function parseAssetId(assetId: string): { currency: string; issuer: string } | null {\n    const parts = assetId.split('.');\n    if (parts.length !== 2) {\n        return null;\n    }\n    return {\n        currency: parts[0],\n        issuer: parts[1]\n    };\n}\n\nexport function isValidXRPLAddress(address: string): boolean {\n    const xrplAddressRegex = /^r[1-9A-HJ-NP-Za-km-z]{25,34}$/;\n    return xrplAddressRegex.test(address);\n}\n\nexport function dropsToXrp(drops: string | number): number {\n    return Number(drops) / 1000000;\n}\n\nexport function xrpToDrops(xrp: string | number): string {\n    return (Number(xrp) * 1000000).toString();\n}\n\nexport function formatTransactionResult(result: any): {\n    hash: string;\n    ledgerIndex: number;\n    fee: string;\n    success: boolean;\n    errorCode?: string;\n    errorMessage?: string;\n} {\n    return {\n        hash: result.hash,\n        ledgerIndex: result.ledger_index,\n        fee: result.Fee,\n        success: result.meta?.TransactionResult === 'tesSUCCESS',\n        errorCode: result.meta?.TransactionResult !== 'tesSUCCESS' ? result.meta?.TransactionResult : undefined,\n        errorMessage: result.meta?.TransactionResult !== 'tesSUCCESS' ? 'Transaction failed' : undefined\n    };\n}\n\nexport function createTrustlineAmount(value: string | number, currency: string, issuer: string): any {\n    return {\n        value: value.toString(),\n        currency: currency,\n        issuer: issuer\n    };\n}\n\nexport function createXRPAmount(xrp: string | number): string {\n    return xrpToDrops(xrp);\n}\n\nexport function calculateNetworkFee(transactionCount: number = 1): string {\n    // Standard XRPL fee is 12 drops per transaction\n    const standardFee = 12;\n    const totalFee = standardFee * transactionCount;\n    return totalFee.toString();\n}\n\nexport function generateDistributionReference(assetId: string, timestamp?: number): string {\n    const ts = timestamp || Date.now();\n    const [currency] = assetId.split('.');\n    return `${currency}-DIST-${ts}`;\n}\n\nexport function validateLedgerResponse(response: any): boolean {\n    return response &&\n        response.result &&\n        response.result.status === 'success' &&\n        response.result.validated === true;\n}\n\nexport function extractAccountLines(accountLinesResponse: any): Array<{\n    account: string;\n    balance: string;\n    currency: string;\n    limit: string;\n    quality_in?: number;\n    quality_out?: number;\n}> {\n    if (!validateLedgerResponse(accountLinesResponse)) {\n        return [];\n    }\n\n    return accountLinesResponse.result.lines || [];\n}\n\nexport function findTrustline(accountLines: any[], currency: string, issuer: string): any | null {\n    return accountLines.find(line =>\n        line.currency === currency &&\n        line.account === issuer\n    ) || null;\n}\n\nexport function calculateTokenHolderBalance(\n    trustlineBalance: string,\n    totalSupply: number,\n    assetValue: number\n): {\n    tokenBalance: number;\n    dollarValue: number;\n    percentageHolding: number;\n} {\n    const tokenBalance = Math.abs(Number(trustlineBalance)); // Trustline balance is negative for holders\n    const percentageHolding = (tokenBalance / totalSupply) * 100;\n    const dollarValue = (tokenBalance / totalSupply) * assetValue;\n\n    return {\n        tokenBalance,\n        dollarValue,\n        percentageHolding\n    };\n}\n\nexport function createRWAMemo(assetMetadata: any): any {\n    const memoData = {\n        type: \"RWA_TOKENIZATION\",\n        format: \"application/json\",\n        data: assetMetadata\n    };\n\n    const memoJson = JSON.stringify(memoData);\n    const memoHex = convertStringToHex(memoJson);\n\n    return {\n        Memo: {\n            MemoType: convertStringToHex(\"RWA_TOKENIZATION\"),\n            MemoFormat: convertStringToHex(\"application/json\"),\n            MemoData: memoHex\n        }\n    };\n}\n\nexport function parseRWAMemo(memo: any): any | null {\n    try {\n        if (!memo.MemoType || !memo.MemoData) {\n            return null;\n        }\n\n        const memoType = convertHexToString(memo.MemoType);\n\n        if (memoType !== 'RWA_TOKENIZATION') {\n            return null;\n        }\n\n        const memoDataJson = convertHexToString(memo.MemoData);\n        const memoData = JSON.parse(memoDataJson);\n\n        return memoData.data;\n    } catch (error) {\n        console.error('Failed to parse RWA memo:', error);\n        return null;\n    }\n}\n\nexport function findRWATokenizationTx(transactions: any[], currency: string): any | null {\n    for (const txWrapper of transactions) {\n        const tx = txWrapper.tx;\n\n        if (tx.TransactionType === 'AccountSet' && tx.Memos) {\n            for (const memoWrapper of tx.Memos) {\n                const parsedMemo = parseRWAMemo(memoWrapper.Memo);\n\n                if (parsedMemo && parsedMemo.assetDetails?.tokenSymbol === currency) {\n                    return {\n                        ...parsedMemo,\n                        tokenizationTxHash: tx.hash,\n                        ledgerIndex: txWrapper.ledger_index\n                    };\n                }\n            }\n        }\n    }\n\n    return null;\n}\n\nexport function getColdWallet(): Wallet {\n    // FIXME: not safe to have it here\n    // rHJZf5qYxwH2Fnms1Uwmi61VfHqoTALgXw\n    const coldPKey = atob(\"c0VkN1FnTEhnSENya3NVZnhHSjg0cWpOdlZxM0VlWQ==\")\n    return Wallet.fromSeed(coldPKey)\n}","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\nimport { AMMDeposit, xrpToDrops } from 'xrpl';\n\n// NOT TESTED YET\n\nexport const AddLiquidityAMMTool: McpTool = {\n    name: \"rwa_add_liquidity_amm\",\n    description: \"Add liquidity to an existing AMM pool and receive LP tokens\",\n    schema: {\n        token_id: z.string()\n            .regex(/^[A-Z0-9]{3}\\.r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n            .describe(\"Token ID in format 'CURRENCY.ISSUER' (e.g., 'PAT.rHJZf5qYxwH2Fnms1Uwmi61VfHqoTALgXw')\"),\n        deposit_type: z.enum(['both_assets', 'single_asset_token', 'single_asset_xrp'])\n            .default('both_assets')\n            .describe(\"Type of deposit: both assets (balanced), single token, or single XRP\"),\n        token_amount: z.number()\n            .positive()\n            .optional()\n            .describe(\"Amount of RWA tokens to deposit (required for both_assets and single_asset_token)\"),\n        xrp_amount: z.number()\n            .positive()\n            .optional()\n            .describe(\"Amount of XRP to deposit (required for both_assets and single_asset_xrp)\"),\n        lp_tokens_out: z.number()\n            .positive()\n            .optional()\n            .describe(\"Exact amount of LP tokens to receive (alternative to specifying amounts)\"),\n        slippage_tolerance: z.number()\n            .min(0.1)\n            .max(50)\n            .default(2.0)\n            .describe(\"Maximum acceptable slippage percentage (default: 2%)\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            // Parse token ID\n            const [currency, issuer] = input.token_id.split('.');\n\n            // Check if AMM exists for this pair\n            let ammInfo: any;\n            try {\n                ammInfo = await agent.client.request({\n                    command: 'amm_info',\n                    asset: {\n                        currency: currency,\n                        issuer: issuer\n                    },\n                    asset2: {\n                        currency: \"XRP\"\n                    }\n                });\n            } catch (error: any) {\n                throw new Error(`No AMM found for ${currency}/XRP pair. Create an AMM first.`);\n            }\n\n            const amm = ammInfo.result.amm;\n            const tokenPool = parseFloat(amm.amount.value);\n            const xrpPool = Number(amm.amount2) / 1000000; // Convert drops to XRP\n            const totalLPTokens = parseFloat(amm.lp_token.value);\n\n            // Validate user balances\n            const balances = await agent.getRWATokenBalances();\n            const userTokenBalance = balances.rwa_tokens.find(\n                token => token.currency === currency && token.issuer === issuer\n            )?.balance || 0;\n            const userXRPBalance = balances.xrp_balance;\n\n            // Validate inputs based on deposit type\n            if (input.deposit_type === 'both_assets') {\n                if (!input.token_amount || !input.xrp_amount) {\n                    throw new Error(\"Both token_amount and xrp_amount required for balanced deposit\");\n                }\n                \n                if (userTokenBalance < input.token_amount) {\n                    throw new Error(`Insufficient token balance. Available: ${userTokenBalance}, Required: ${input.token_amount}`);\n                }\n                \n                if (userXRPBalance < (input.xrp_amount + 11)) { // Reserve 11 XRP for fees/reserves\n                    throw new Error(`Insufficient XRP balance. Available: ${userXRPBalance}, Required: ${input.xrp_amount + 11}`);\n                }\n            } else if (input.deposit_type === 'single_asset_token') {\n                if (!input.token_amount) {\n                    throw new Error(\"token_amount required for single token deposit\");\n                }\n                \n                if (userTokenBalance < input.token_amount) {\n                    throw new Error(`Insufficient token balance. Available: ${userTokenBalance}, Required: ${input.token_amount}`);\n                }\n            } else if (input.deposit_type === 'single_asset_xrp') {\n                if (!input.xrp_amount) {\n                    throw new Error(\"xrp_amount required for single XRP deposit\");\n                }\n                \n                if (userXRPBalance < (input.xrp_amount + 11)) {\n                    throw new Error(`Insufficient XRP balance. Available: ${userXRPBalance}, Required: ${input.xrp_amount + 11}`);\n                }\n            }\n\n            // Calculate expected LP tokens based on deposit type\n            let expectedLPTokens = 0;\n            let depositRatio = 0;\n\n            if (input.deposit_type === 'both_assets') {\n                // For balanced deposits: LP tokens proportional to share of pool\n                const tokenShare = input.token_amount / tokenPool;\n                const xrpShare = input.xrp_amount / xrpPool;\n                depositRatio = Math.min(tokenShare, xrpShare); // Use smaller ratio\n                expectedLPTokens = depositRatio * totalLPTokens;\n            } else {\n                // For single asset deposits: use simplified formula (subject to trading fees)\n                if (input.deposit_type === 'single_asset_token') {\n                    depositRatio = input.token_amount / tokenPool;\n                } else {\n                    depositRatio = input.xrp_amount / xrpPool;\n                }\n                // Single asset deposits receive fewer LP tokens due to trading fees\n                const tradingFeeRate = amm.trading_fee / 100000;\n                expectedLPTokens = (depositRatio * totalLPTokens) * (1 - tradingFeeRate);\n            }\n\n            // Prepare AMMDeposit transaction\n            let ammDeposit: AMMDeposit = {\n                TransactionType: 'AMMDeposit',\n                Account: agent.wallet.address,\n                Asset: {\n                    currency: currency,\n                    issuer: issuer\n                },\n                Asset2: {\n                    currency: \"XRP\"\n                },\n                Fee: '12'\n            };\n\n            // Set flags and amounts based on deposit type\n            if (input.deposit_type === 'both_assets') {\n                ammDeposit.Flags = 0x00100000; // tfTwoAsset\n                ammDeposit.Amount = {\n                    currency: currency,\n                    issuer: issuer,\n                    value: input.token_amount.toString()\n                };\n                ammDeposit.Amount2 = xrpToDrops(input.xrp_amount);\n            } else if (input.deposit_type === 'single_asset_token') {\n                ammDeposit.Flags = 0x00080000; // tfSingleAsset\n                ammDeposit.Amount = {\n                    currency: currency,\n                    issuer: issuer,\n                    value: input.token_amount.toString()\n                };\n            } else if (input.deposit_type === 'single_asset_xrp') {\n                ammDeposit.Flags = 0x00080000; // tfSingleAsset\n                ammDeposit.Amount2 = xrpToDrops(input.xrp_amount);\n            }\n\n            // Add LP token expectation if specified\n            if (input.lp_tokens_out) {\n                ammDeposit.LPTokenOut = {\n                    currency: amm.lp_token.currency,\n                    issuer: amm.lp_token.issuer,\n                    value: input.lp_tokens_out.toString()\n                };\n            }\n\n            // Submit the transaction\n            const result: any = await agent.client.submitAndWait(ammDeposit, { wallet: agent.wallet });\n\n            if (result.result.meta?.TransactionResult !== 'tesSUCCESS') {\n                throw new Error(`Liquidity addition failed: ${result.result.meta?.TransactionResult}`);\n            }\n\n            // Get updated AMM info\n            const updatedAMMInfo: any = await agent.client.request({\n                command: 'amm_info',\n                asset: {\n                    currency: currency,\n                    issuer: issuer\n                },\n                asset2: {\n                    currency: \"XRP\"\n                }\n            });\n\n            const updatedAMM = updatedAMMInfo.result.amm;\n            const newTokenPool = parseFloat(updatedAMM.amount.value);\n            const newXRPPool = Number(updatedAMM.amount2) / 1000000;\n            const newTotalLPTokens = parseFloat(updatedAMM.lp_token.value);\n\n            // Calculate actual LP tokens received (from transaction metadata)\n            let actualLPTokensReceived = 0;\n            // This would need to be extracted from transaction metadata\n            // For now, estimate based on pool changes\n            actualLPTokensReceived = newTotalLPTokens - totalLPTokens;\n\n            // Calculate new pool share\n            const newPoolShare = (actualLPTokensReceived / newTotalLPTokens) * 100;\n\n            // Get updated user balances\n            const updatedBalances = await agent.getRWATokenBalances();\n\n            return {\n                status: \"success\",\n                message: `✅ Successfully added liquidity to ${currency}/XRP pool`,\n                transaction_info: {\n                    hash: result.result.hash,\n                    ledger_index: result.result.ledger_index,\n                    fee_paid: `${Number(ammDeposit.Fee) / 1000000} XRP`,\n                    validated: result.result.validated\n                },\n                deposit_details: {\n                    deposit_type: input.deposit_type,\n                    token_deposited: input.token_amount || 0,\n                    xrp_deposited: input.xrp_amount || 0,\n                    lp_tokens_received: actualLPTokensReceived,\n                    pool_share_percentage: newPoolShare.toFixed(4)\n                },\n                pool_metrics: {\n                    before: {\n                        token_pool: `${tokenPool} ${currency}`,\n                        xrp_pool: `${xrpPool} XRP`,\n                        total_lp_tokens: totalLPTokens,\n                        pool_ratio: `1 ${currency} = ${(xrpPool / tokenPool).toFixed(6)} XRP`\n                    },\n                    after: {\n                        token_pool: `${newTokenPool} ${currency}`,\n                        xrp_pool: `${newXRPPool} XRP`,\n                        total_lp_tokens: newTotalLPTokens,\n                        pool_ratio: `1 ${currency} = ${(newXRPPool / newTokenPool).toFixed(6)} XRP`\n                    }\n                },\n                lp_token_info: {\n                    currency: amm.lp_token.currency,\n                    issuer: amm.lp_token.issuer,\n                    your_lp_balance: actualLPTokensReceived,\n                    estimated_value: `${((newPoolShare / 100) * (newTokenPool + newXRPPool)).toFixed(2)} units`,\n                    voting_power: `${newPoolShare.toFixed(4)}% of pool decisions`\n                },\n                earnings_potential: {\n                    trading_fee_rate: `${amm.trading_fee / 100}%`,\n                    estimated_daily_volume: \"Monitoring required\",\n                    projected_yield: \"Based on trading activity\",\n                    impermanent_loss_risk: input.deposit_type === 'both_assets' ? \"Low (balanced)\" : \"Higher (single asset)\"\n                },\n                next_steps: [\n                    \"Monitor your LP token balance and pool performance\",\n                    \"Track trading fees earned from pool activity\", \n                    \"Consider rebalancing if pool ratio changes significantly\",\n                    \"Use rwa_remove_liquidity_amm to withdraw when needed\"\n                ],\n                warnings: [\n                    \"⚠️ Impermanent loss risk due to price volatility\",\n                    \"⚠️ LP tokens can be traded but affect your pool share\",\n                    input.deposit_type !== 'both_assets' ? \"⚠️ Single asset deposits pay trading fees\" : \"\"\n                ].filter(w => w)\n            };\n\n        } catch (error: any) {\n            throw new Error(`Failed to add liquidity to AMM: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\nimport { AMMWithdraw, xrpToDrops } from 'xrpl';\n\n// NOT TESTED YET\n\nexport const RemoveLiquidityAMMTool: McpTool = {\n    name: \"rwa_remove_liquidity_amm\",\n    description: \"Remove liquidity from an AMM pool by redeeming LP tokens\",\n    schema: {\n        token_id: z.string()\n            .regex(/^[A-Z0-9]{3}\\.r[1-9A-HJ-NP-Za-km-z]{25,34}$/)\n            .describe(\"Token ID in format 'CURRENCY.ISSUER' (e.g., 'PAT.rHJZf5qYxwH2Fnms1Uwmi61VfHqoTALgXw')\"),\n        withdrawal_type: z.enum(['both_assets', 'single_asset_token', 'single_asset_xrp', 'lp_tokens_amount'])\n            .default('both_assets')\n            .describe(\"Type of withdrawal: both assets (proportional), single asset, or specify LP token amount\"),\n        lp_tokens_amount: z.number()\n            .positive()\n            .optional()\n            .describe(\"Amount of LP tokens to redeem (required for lp_tokens_amount type)\"),\n        token_amount_out: z.number()\n            .positive()\n            .optional()\n            .describe(\"Desired amount of tokens to receive (for single_asset_token)\"),\n        xrp_amount_out: z.number()\n            .positive()\n            .optional()\n            .describe(\"Desired amount of XRP to receive (for single_asset_xrp)\"),\n        percentage_to_withdraw: z.number()\n            .min(0.1)\n            .max(100)\n            .optional()\n            .describe(\"Percentage of your LP position to withdraw (1-100%)\"),\n        slippage_tolerance: z.number()\n            .min(0.1)\n            .max(50)\n            .default(2.0)\n            .describe(\"Maximum acceptable slippage percentage (default: 2%)\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            await agent.connect();\n\n            // Parse token ID\n            const [currency, issuer] = input.token_id.split('.');\n\n            // Check if AMM exists for this pair\n            let ammInfo: any;\n            try {\n                ammInfo = await agent.client.request({\n                    command: 'amm_info',\n                    asset: {\n                        currency: currency,\n                        issuer: issuer\n                    },\n                    asset2: {\n                        currency: \"XRP\"\n                    }\n                });\n            } catch (error: any) {\n                throw new Error(`No AMM found for ${currency}/XRP pair.`);\n            }\n\n            const amm = ammInfo.result.amm;\n            const tokenPool = parseFloat(amm.amount.value);\n            const xrpPool = Number(amm.amount2) / 1000000; // Convert drops to XRP\n            const totalLPTokens = parseFloat(amm.lp_token.value);\n\n            // Check user's LP token balance\n            const balances = await agent.getRWATokenBalances();\n            const userLPBalance = balances.rwa_tokens.find(\n                token => token.currency === amm.lp_token.currency && token.issuer === amm.lp_token.issuer\n            )?.balance || 0;\n\n            if (userLPBalance === 0) {\n                throw new Error(`You don't have any LP tokens for ${currency}/XRP pool. Add liquidity first.`);\n            }\n\n            // Calculate LP tokens to redeem based on input\n            let lpTokensToRedeem = 0;\n\n            if (input.withdrawal_type === 'lp_tokens_amount') {\n                if (!input.lp_tokens_amount) {\n                    throw new Error(\"lp_tokens_amount required for this withdrawal type\");\n                }\n                lpTokensToRedeem = input.lp_tokens_amount;\n            } else if (input.percentage_to_withdraw) {\n                lpTokensToRedeem = (input.percentage_to_withdraw / 100) * userLPBalance;\n            } else {\n                // Default to withdrawing all LP tokens for proportional withdrawal\n                lpTokensToRedeem = userLPBalance;\n            }\n\n            if (lpTokensToRedeem > userLPBalance) {\n                throw new Error(`Insufficient LP tokens. Available: ${userLPBalance}, Requested: ${lpTokensToRedeem}`);\n            }\n\n            // Calculate expected outputs\n            const withdrawalRatio = lpTokensToRedeem / totalLPTokens;\n            const expectedTokenOut = tokenPool * withdrawalRatio;\n            const expectedXRPOut = xrpPool * withdrawalRatio;\n\n            // Validate single asset withdrawal requests\n            if (input.withdrawal_type === 'single_asset_token' && input.token_amount_out) {\n                if (input.token_amount_out > expectedTokenOut * 1.1) { // Allow 10% buffer\n                    throw new Error(`Requested token amount too high. Maximum available: ~${expectedTokenOut.toFixed(6)}`);\n                }\n            } else if (input.withdrawal_type === 'single_asset_xrp' && input.xrp_amount_out) {\n                if (input.xrp_amount_out > expectedXRPOut * 1.1) {\n                    throw new Error(`Requested XRP amount too high. Maximum available: ~${expectedXRPOut.toFixed(6)}`);\n                }\n            }\n\n            // Prepare AMMWithdraw transaction\n            let ammWithdraw: AMMWithdraw = {\n                TransactionType: 'AMMWithdraw',\n                Account: agent.wallet.address,\n                Asset: {\n                    currency: currency,\n                    issuer: issuer\n                },\n                Asset2: {\n                    currency: \"XRP\"\n                },\n                LPTokenIn: {\n                    currency: amm.lp_token.currency,\n                    issuer: amm.lp_token.issuer,\n                    value: lpTokensToRedeem.toString()\n                },\n                Fee: '12'\n            };\n\n            // Set flags and amounts based on withdrawal type\n            if (input.withdrawal_type === 'both_assets') {\n                ammWithdraw.Flags = 0x00100000; // tfTwoAsset\n                // For proportional withdrawal, amounts are calculated automatically\n            } else if (input.withdrawal_type === 'single_asset_token') {\n                ammWithdraw.Flags = 0x00080000; // tfSingleAsset\n                ammWithdraw.Amount = {\n                    currency: currency,\n                    issuer: issuer,\n                    value: (input.token_amount_out || expectedTokenOut).toString()\n                };\n            } else if (input.withdrawal_type === 'single_asset_xrp') {\n                ammWithdraw.Flags = 0x00080000; // tfSingleAsset\n                ammWithdraw.Amount2 = xrpToDrops(input.xrp_amount_out || expectedXRPOut);\n            } else if (input.withdrawal_type === 'lp_tokens_amount') {\n                ammWithdraw.Flags = 0x00200000; // tfLPToken\n            }\n\n            // Submit the transaction\n            const result: any = await agent.client.submitAndWait(ammWithdraw, { wallet: agent.wallet });\n\n            if (result.result.meta?.TransactionResult !== 'tesSUCCESS') {\n                throw new Error(`Liquidity removal failed: ${result.result.meta?.TransactionResult}`);\n            }\n\n            // Get updated AMM info\n            const updatedAMMInfo: any = await agent.client.request({\n                command: 'amm_info',\n                asset: {\n                    currency: currency,\n                    issuer: issuer\n                },\n                asset2: {\n                    currency: \"XRP\"\n                }\n            });\n\n            const updatedAMM = updatedAMMInfo.result.amm;\n            const newTokenPool = parseFloat(updatedAMM.amount.value);\n            const newXRPPool = Number(updatedAMM.amount2) / 1000000;\n            const newTotalLPTokens = parseFloat(updatedAMM.lp_token.value);\n\n            // Calculate actual amounts received (would need to parse from transaction metadata)\n            const actualTokenReceived = tokenPool - newTokenPool;\n            const actualXRPReceived = xrpPool - newXRPPool;\n\n            // Get updated user balances\n            const updatedBalances = await agent.getRWATokenBalances();\n            const newUserLPBalance = updatedBalances.rwa_tokens.find(\n                token => token.currency === amm.lp_token.currency && token.issuer === amm.lp_token.issuer\n            )?.balance || 0;\n\n            // Calculate new pool share\n            const newPoolShare = newTotalLPTokens > 0 ? (newUserLPBalance / newTotalLPTokens) * 100 : 0;\n\n            // Calculate withdrawal fee (for single asset withdrawals)\n            const tradingFeeRate = amm.trading_fee / 100000;\n            const withdrawalFee = input.withdrawal_type.includes('single_asset') ? \n                `~${(withdrawalRatio * tradingFeeRate * 100).toFixed(4)}%` : \"None (balanced withdrawal)\";\n\n            return {\n                status: \"success\",\n                message: `✅ Successfully removed liquidity from ${currency}/XRP pool`,\n                transaction_info: {\n                    hash: result.result.hash,\n                    ledger_index: result.result.ledger_index,\n                    fee_paid: `${Number(ammWithdraw.Fee) / 1000000} XRP`,\n                    validated: result.result.validated\n                },\n                withdrawal_details: {\n                    withdrawal_type: input.withdrawal_type,\n                    lp_tokens_redeemed: lpTokensToRedeem,\n                    tokens_received: actualTokenReceived > 0 ? `${actualTokenReceived.toFixed(6)} ${currency}` : \"0\",\n                    xrp_received: actualXRPReceived > 0 ? `${actualXRPReceived.toFixed(6)} XRP` : \"0\",\n                    withdrawal_fee: withdrawalFee\n                },\n                pool_metrics: {\n                    before: {\n                        token_pool: `${tokenPool} ${currency}`,\n                        xrp_pool: `${xrpPool} XRP`,\n                        total_lp_tokens: totalLPTokens,\n                        your_lp_balance: userLPBalance,\n                        your_pool_share: `${(userLPBalance / totalLPTokens * 100).toFixed(4)}%`\n                    },\n                    after: {\n                        token_pool: `${newTokenPool} ${currency}`,\n                        xrp_pool: `${newXRPPool} XRP`,\n                        total_lp_tokens: newTotalLPTokens,\n                        your_lp_balance: newUserLPBalance,\n                        your_pool_share: `${newPoolShare.toFixed(4)}%`\n                    }\n                },\n                impact_analysis: {\n                    pool_liquidity_change: `${((newTotalLPTokens - totalLPTokens) / totalLPTokens * 100).toFixed(2)}%`,\n                    price_impact: `${(Math.abs((newXRPPool / newTokenPool) - (xrpPool / tokenPool)) / (xrpPool / tokenPool) * 100).toFixed(4)}%`,\n                    remaining_position_value: newUserLPBalance > 0 ? \n                        `~${((newUserLPBalance / newTotalLPTokens) * (newTokenPool + newXRPPool)).toFixed(2)} units` : \"0\"\n                },\n                earnings_summary: {\n                    trading_fees_earned: \"Calculate based on historical activity\",\n                    impermanent_loss_realized: input.withdrawal_type === 'both_assets' ? \n                        \"Proportional to price changes since deposit\" : \"Additional loss from single asset withdrawal\",\n                    net_position_change: \"Compare initial deposit value vs current withdrawal value\"\n                },\n                next_steps: [\n                    newUserLPBalance > 0 ? \"Monitor remaining LP position\" : \"Position fully closed\",\n                    \"Track received assets in your wallet\",\n                    \"Consider tax implications of LP token redemption\",\n                    actualTokenReceived > 0 ? `Manage received ${currency} tokens` : \"\",\n                    actualXRPReceived > 0 ? `Utilize received XRP` : \"\"\n                ].filter(step => step),\n                warnings: [\n                    input.withdrawal_type.includes('single_asset') ? \"⚠️ Single asset withdrawal incurred trading fees\" : \"\",\n                    \"⚠️ Impermanent loss may have occurred since initial deposit\",\n                    newUserLPBalance === 0 ? \"⚠️ No remaining LP position - consider re-entering if profitable\" : \"\"\n                ].filter(w => w)\n            };\n\n        } catch (error: any) {\n            throw new Error(`Failed to remove liquidity from AMM: ${error.message}`);\n        } finally {\n            await agent.disconnect();\n        }\n    }\n};\n","import { z } from \"zod\";\nimport { RWAAgent } from \"../../agent\";\nimport { type McpTool } from \"../../types\";\n\nexport const GenerateWebappProjectTool: McpTool = {\n    name: \"rwa_generate_webapp_project\",\n    description: \"Generate a complete functional RWA webapp project with all necessary files and components\",\n    schema: {\n        project_name: z.string()\n            .min(3)\n            .max(50)\n            .regex(/^[a-zA-Z0-9-_]+$/)\n            .describe(\"Name of the webapp project (e.g., 'bangkok-condo-platform')\"),\n        asset_info: z.object({\n            name: z.string().describe(\"Asset name (e.g., 'Bangkok Condo Complex')\"),\n            symbol: z.string().length(3).describe(\"Token symbol (e.g., 'BKC')\"),\n            type: z.enum(['real_estate', 'treasury', 'commodity', 'bond']).describe(\"Asset type\"),\n            total_value: z.number().positive().describe(\"Total asset value in USD\"),\n            yield_rate: z.number().min(0).max(50).describe(\"Annual yield percentage\")\n        }).describe(\"Information about the RWA asset\"),\n        project_type: z.enum(['investor_portal', 'trading_platform', 'admin_dashboard', 'full_platform'])\n            .default('full_platform')\n            .describe(\"Type of webapp to generate\"),\n        features: z.array(z.enum([\n            'asset_overview',\n            'token_purchase',\n            'portfolio_dashboard', \n            'yield_tracking',\n            'trading_interface',\n            'liquidity_provision',\n            'admin_controls',\n            'investor_kyc',\n            'document_vault',\n            'analytics_dashboard'\n        ]))\n            .default(['asset_overview', 'token_purchase', 'portfolio_dashboard'])\n            .describe(\"Features to include in the webapp\"),\n        styling_theme: z.enum(['modern_dark', 'corporate_light', 'fintech_blue', 'real_estate_green'])\n            .default('fintech_blue')\n            .describe(\"Visual theme for the webapp\"),\n        wallet_integration: z.array(z.enum(['xumm', 'metamask', 'walletconnect', 'crossmark']))\n            .default(['xumm'])\n            .describe(\"Wallet integrations to include\")\n    },\n    handler: async (agent: RWAAgent, input: Record<string, any>) => {\n        try {\n            const projectName = input.project_name;\n            const assetInfo = input.asset_info;\n            \n            // Generate project structure\n            const projectStructure = generateProjectStructure(projectName, input);\n            \n            // Generate configuration files\n            const configs = generateConfigFiles(projectName, assetInfo, input);\n            \n            // Generate React components\n            const components = generateReactComponents(assetInfo, input.features, input.styling_theme);\n            \n            // Generate API endpoints  \n            const apiEndpoints = generateAPIEndpoints(assetInfo, input.features);\n            \n            // Generate smart contract integration\n            const contractIntegration = generateContractIntegration(assetInfo);\n            \n            // Generate documentation\n            const documentation = generateDocumentation(projectName, assetInfo, input);\n\n            return {\n                status: \"success\",\n                message: `✅ Generated complete RWA webapp: ${projectName}`,\n                project_details: {\n                    name: projectName,\n                    asset_name: assetInfo.name,\n                    asset_symbol: assetInfo.symbol,\n                    asset_type: assetInfo.type,\n                    project_type: input.project_type,\n                    features_count: input.features.length,\n                    theme: input.styling_theme,\n                    wallet_support: input.wallet_integration\n                },\n                generated_structure: projectStructure,\n                configuration_files: configs,\n                react_components: components,\n                api_endpoints: apiEndpoints,\n                contract_integration: contractIntegration,\n                documentation: documentation,\n                deployment_info: {\n                    development: {\n                        setup_commands: [\n                            `cd ${projectName}`,\n                            \"npm install\",\n                            \"npm run setup:env\", \n                            \"npm run dev\"\n                        ],\n                        local_url: `http://localhost:3000`,\n                        admin_url: `http://localhost:3000/admin`\n                    },\n                    production: {\n                        build_command: \"npm run build\",\n                        deployment_targets: [\"Vercel\", \"Netlify\", \"AWS\", \"Azure\"],\n                        environment_variables: [\n                            \"NEXT_PUBLIC_XRPL_NETWORK\",\n                            \"NEXT_PUBLIC_TOKEN_ISSUER\",\n                            \"NEXT_PUBLIC_AMM_ACCOUNT\",\n                            \"DATABASE_URL\",\n                            \"JWT_SECRET\"\n                        ]\n                    }\n                },\n                integration_steps: [\n                    \"✅ Project files generated successfully\",\n                    \"🔄 NEXT: Configure environment variables\",\n                    \"🔄 THEN: Deploy to staging environment\", \n                    \"🔄 FINALLY: Configure domain and SSL\",\n                    \"📚 See README.md for detailed setup instructions\"\n                ],\n                live_demo_url: `https://${projectName}.vercel.app`,\n                admin_credentials: {\n                    default_admin: \"admin@example.com\",\n                    default_password: \"change-me-immediately\",\n                    setup_url: `/admin/setup`\n                },\n                investor_onboarding: {\n                    public_url: `/${assetInfo.symbol.toLowerCase()}`,\n                    investment_minimum: `$${Math.round(assetInfo.total_value / 1000)}`,\n                    kyc_required: input.features.includes('investor_kyc'),\n                    wallet_required: true\n                },\n                asset_integration: {\n                    token_contract: assetInfo.symbol,\n                    amm_pool: `${assetInfo.symbol}/XRP`,\n                    total_tokens: Math.round(assetInfo.total_value / 1000),\n                    current_price: `$1000 per token`,\n                    yield_rate: `${assetInfo.yield_rate}% annually`\n                },\n                success_metrics: {\n                    time_to_deploy: \"< 10 minutes\",\n                    investor_onboarding: \"< 2 minutes\", \n                    transaction_speed: \"< 5 seconds\",\n                    mobile_responsive: true,\n                    seo_optimized: true,\n                    accessibility_compliant: true\n                }\n            };\n        } catch (error: any) {\n            throw new Error(`Failed to generate webapp project: ${error.message}`);\n        }\n    }\n};\n\n// Helper function to generate project structure\nfunction generateProjectStructure(projectName: string, input: any): any {\n    return {\n        [`${projectName}/`]: {\n            type: \"directory\",\n            children: {\n                \"frontend/\": {\n                    type: \"directory\", \n                    description: \"Next.js frontend application\",\n                    children: {\n                        \"components/\": {\n                            type: \"directory\",\n                            children: {\n                                \"AssetOverview.tsx\": { type: \"file\", description: \"Asset information display\" },\n                                \"TokenPurchase.tsx\": { type: \"file\", description: \"Token buying interface\" },\n                                \"PortfolioDashboard.tsx\": { type: \"file\", description: \"Investor portfolio\" },\n                                \"TradingInterface.tsx\": { type: \"file\", description: \"AMM trading UI\" },\n                                \"WalletConnector.tsx\": { type: \"file\", description: \"Multi-wallet integration\" },\n                                \"YieldTracker.tsx\": { type: \"file\", description: \"Yield distribution tracking\" }\n                            }\n                        },\n                        \"pages/\": {\n                            type: \"directory\",\n                            children: {\n                                \"index.tsx\": { type: \"file\", description: \"Landing page\" },\n                                \"invest.tsx\": { type: \"file\", description: \"Investment portal\" },\n                                \"portfolio.tsx\": { type: \"file\", description: \"Portfolio management\" },\n                                \"trade.tsx\": { type: \"file\", description: \"Trading interface\" },\n                                \"admin/\": {\n                                    type: \"directory\",\n                                    children: {\n                                        \"index.tsx\": { type: \"file\", description: \"Admin dashboard\" },\n                                        \"assets.tsx\": { type: \"file\", description: \"Asset management\" },\n                                        \"investors.tsx\": { type: \"file\", description: \"Investor management\" }\n                                    }\n                                }\n                            }\n                        },\n                        \"styles/\": {\n                            type: \"directory\",\n                            children: {\n                                \"globals.css\": { type: \"file\", description: \"Global styles\" },\n                                \"themes.css\": { type: \"file\", description: \"Theme configuration\" }\n                            }\n                        },\n                        \"utils/\": {\n                            type: \"directory\", \n                            children: {\n                                \"xrpl.ts\": { type: \"file\", description: \"XRPL integration utilities\" },\n                                \"rwa.ts\": { type: \"file\", description: \"RWA token utilities\" },\n                                \"amm.ts\": { type: \"file\", description: \"AMM interaction utilities\" }\n                            }\n                        }\n                    }\n                },\n                \"backend/\": {\n                    type: \"directory\",\n                    description: \"Express.js API server\",\n                    children: {\n                        \"routes/\": {\n                            type: \"directory\",\n                            children: {\n                                \"assets.js\": { type: \"file\", description: \"Asset management API\" },\n                                \"trading.js\": { type: \"file\", description: \"Trading API endpoints\" },\n                                \"portfolio.js\": { type: \"file\", description: \"Portfolio API\" },\n                                \"admin.js\": { type: \"file\", description: \"Admin API endpoints\" }\n                            }\n                        },\n                        \"middleware/\": {\n                            type: \"directory\",\n                            children: {\n                                \"auth.js\": { type: \"file\", description: \"Authentication middleware\" },\n                                \"validation.js\": { type: \"file\", description: \"Input validation\" },\n                                \"rateLimit.js\": { type: \"file\", description: \"Rate limiting\" }\n                            }\n                        },\n                        \"services/\": {\n                            type: \"directory\",\n                            children: {\n                                \"xrplService.js\": { type: \"file\", description: \"XRPL integration service\" },\n                                \"rwaService.js\": { type: \"file\", description: \"RWA token service\" },\n                                \"ammService.js\": { type: \"file\", description: \"AMM interaction service\" }\n                            }\n                        }\n                    }\n                },\n                \"database/\": {\n                    type: \"directory\",\n                    description: \"Database schema and migrations\",\n                    children: {\n                        \"migrations/\": { type: \"directory\", description: \"Database migrations\" },\n                        \"schema.sql\": { type: \"file\", description: \"Database schema\" },\n                        \"seeds/\": { type: \"directory\", description: \"Sample data\" }\n                    }\n                },\n                \"docs/\": {\n                    type: \"directory\",\n                    description: \"Project documentation\",\n                    children: {\n                        \"README.md\": { type: \"file\", description: \"Setup and usage guide\" },\n                        \"API.md\": { type: \"file\", description: \"API documentation\" },\n                        \"DEPLOYMENT.md\": { type: \"file\", description: \"Deployment guide\" },\n                        \"INVESTOR_GUIDE.md\": { type: \"file\", description: \"Investor instructions\" }\n                    }\n                },\n                \"config/\": {\n                    type: \"directory\",\n                    description: \"Configuration files\",\n                    children: {\n                        \"next.config.js\": { type: \"file\", description: \"Next.js configuration\" },\n                        \"tailwind.config.js\": { type: \"file\", description: \"Tailwind CSS config\" },\n                        \"package.json\": { type: \"file\", description: \"Dependencies and scripts\" },\n                        \".env.example\": { type: \"file\", description: \"Environment variables template\" }\n                    }\n                }\n            }\n        }\n    };\n}\n\n// Helper function to generate configuration files\nfunction generateConfigFiles(projectName: string, assetInfo: any, input: any): any {\n    return {\n        \"package.json\": {\n            name: projectName,\n            version: \"1.0.0\",\n            description: `RWA platform for ${assetInfo.name}`,\n            scripts: {\n                \"dev\": \"next dev\",\n                \"build\": \"next build\", \n                \"start\": \"next start\",\n                \"setup:env\": \"cp .env.example .env.local\",\n                \"setup:db\": \"npm run db:migrate && npm run db:seed\",\n                \"db:migrate\": \"prisma migrate dev\",\n                \"db:seed\": \"prisma db seed\"\n            },\n            dependencies: {\n                \"next\": \"^14.0.0\",\n                \"react\": \"^18.0.0\",\n                \"react-dom\": \"^18.0.0\",\n                \"xrpl\": \"^2.11.0\",\n                \"@tailwindcss/forms\": \"^0.5.0\",\n                \"recharts\": \"^2.8.0\",\n                \"lucide-react\": \"^0.263.0\"\n            }\n        },\n        \".env.example\": {\n            \"NEXT_PUBLIC_XRPL_NETWORK\": \"testnet\",\n            \"NEXT_PUBLIC_ASSET_SYMBOL\": assetInfo.symbol,\n            \"NEXT_PUBLIC_ASSET_NAME\": assetInfo.name,\n            \"NEXT_PUBLIC_ASSET_VALUE\": assetInfo.total_value.toString(),\n            \"NEXT_PUBLIC_YIELD_RATE\": assetInfo.yield_rate.toString(),\n            \"DATABASE_URL\": \"postgresql://user:password@localhost:5432/rwa_platform\",\n            \"JWT_SECRET\": \"your-jwt-secret-here\",\n            \"ADMIN_EMAIL\": \"admin@example.com\",\n            \"ADMIN_PASSWORD\": \"change-me-immediately\"\n        },\n        \"next.config.js\": {\n            content: `/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  reactStrictMode: true,\n  swcMinify: true,\n  env: {\n    CUSTOM_KEY: process.env.CUSTOM_KEY,\n  },\n  async rewrites() {\n    return [\n      {\n        source: '/api/:path*',\n        destination: 'http://localhost:8000/api/:path*'\n      }\n    ]\n  }\n}\nmodule.exports = nextConfig`\n        },\n        \"tailwind.config.js\": {\n            content: generateTailwindConfig(input.styling_theme)\n        }\n    };\n}\n\n// Helper function to generate React components\nfunction generateReactComponents(assetInfo: any, features: string[], theme: string): any {\n    const components: any = {};\n    \n    if (features.includes('asset_overview')) {\n        components[\"AssetOverview.tsx\"] = {\n            description: \"Displays asset information and key metrics\",\n            props: [\"assetData\", \"priceData\", \"yieldData\"],\n            features: [\"Responsive design\", \"Real-time price updates\", \"Investment calculator\"]\n        };\n    }\n    \n    if (features.includes('token_purchase')) {\n        components[\"TokenPurchase.tsx\"] = {\n            description: \"Token purchase interface with wallet integration\",\n            props: [\"walletConnected\", \"tokenPrice\", \"userBalance\"],\n            features: [\"Multi-wallet support\", \"Slippage protection\", \"Transaction confirmation\"]\n        };\n    }\n    \n    if (features.includes('portfolio_dashboard')) {\n        components[\"PortfolioDashboard.tsx\"] = {\n            description: \"Investor portfolio management interface\",\n            props: [\"portfolioData\", \"transactionHistory\", \"yieldHistory\"],\n            features: [\"Portfolio overview\", \"Performance charts\", \"Transaction history\"]\n        };\n    }\n    \n    if (features.includes('trading_interface')) {\n        components[\"TradingInterface.tsx\"] = {\n            description: \"AMM trading interface for token swaps\",\n            props: [\"ammData\", \"userBalances\", \"slippageTolerance\"],\n            features: [\"Price charts\", \"Order book simulation\", \"Liquidity provision\"]\n        };\n    }\n    \n    return components;\n}\n\n// Helper function to generate API endpoints\nfunction generateAPIEndpoints(assetInfo: any, features: string[]): any {\n    const endpoints: any = {};\n    \n    endpoints[\"/api/assets\"] = {\n        methods: [\"GET\", \"POST\"],\n        description: \"Asset management endpoints\",\n        authentication: \"Required for POST\"\n    };\n    \n    endpoints[\"/api/portfolio\"] = {\n        methods: [\"GET\"],\n        description: \"User portfolio data\",\n        authentication: \"Required\"\n    };\n    \n    if (features.includes('trading_interface')) {\n        endpoints[\"/api/trading\"] = {\n            methods: [\"GET\", \"POST\"],\n            description: \"Trading and AMM interaction\",\n            authentication: \"Required for POST\"\n        };\n    }\n    \n    if (features.includes('admin_controls')) {\n        endpoints[\"/api/admin\"] = {\n            methods: [\"GET\", \"POST\", \"PUT\", \"DELETE\"],\n            description: \"Admin management functions\", \n            authentication: \"Admin required\"\n        };\n    }\n    \n    return endpoints;\n}\n\n// Helper function to generate contract integration\nfunction generateContractIntegration(assetInfo: any): any {\n    return {\n        \"xrpl_integration\": {\n            token_symbol: assetInfo.symbol,\n            issuer_setup: \"Automated issuer account configuration\",\n            trustline_management: \"Automated trustline creation for investors\",\n            amm_integration: \"Native XRPL AMM support\"\n        },\n        \"rwa_features\": {\n            metadata_storage: \"Asset metadata stored in XRPL memos\",\n            yield_distribution: \"Automated yield payments\",\n            compliance_controls: \"KYC and accreditation checking\"\n        }\n    };\n}\n\n// Helper function to generate documentation\nfunction generateDocumentation(projectName: string, assetInfo: any, input: any): any {\n    return {\n        \"README.md\": {\n            sections: [\n                \"Project Overview\",\n                \"Quick Start Guide\", \n                \"Environment Setup\",\n                \"Development Workflow\",\n                \"Deployment Instructions\",\n                \"API Documentation\",\n                \"Troubleshooting\"\n            ],\n            asset_specific: {\n                name: assetInfo.name,\n                symbol: assetInfo.symbol,\n                value: assetInfo.total_value,\n                yield: assetInfo.yield_rate\n            }\n        },\n        \"INVESTOR_GUIDE.md\": {\n            sections: [\n                \"How to Invest\",\n                \"Wallet Setup\",\n                \"Token Purchase Process\",\n                \"Portfolio Management\",\n                \"Yield Collection\",\n                \"Trading Guide\",\n                \"Security Best Practices\"\n            ]\n        },\n        \"API.md\": {\n            endpoints_documented: Object.keys(generateAPIEndpoints(assetInfo, input.features)).length,\n            includes_examples: true,\n            authentication_guide: true\n        }\n    };\n}\n\n// Helper function to generate Tailwind config based on theme\nfunction generateTailwindConfig(theme: string): string {\n    const themeConfigs = {\n        'modern_dark': {\n            primary: '#1f2937',\n            secondary: '#374151', \n            accent: '#3b82f6'\n        },\n        'corporate_light': {\n            primary: '#ffffff',\n            secondary: '#f3f4f6',\n            accent: '#059669'\n        },\n        'fintech_blue': {\n            primary: '#0f172a',\n            secondary: '#1e293b',\n            accent: '#0ea5e9'\n        },\n        'real_estate_green': {\n            primary: '#064e3b',\n            secondary: '#065f46',\n            accent: '#10b981'\n        }\n    };\n    \n    const config = themeConfigs[theme as keyof typeof themeConfigs] || themeConfigs.fintech_blue;\n    \n    return `module.exports = {\n  content: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],\n  theme: {\n    extend: {\n      colors: {\n        primary: '${config.primary}',\n        secondary: '${config.secondary}',\n        accent: '${config.accent}'\n      }\n    }\n  },\n  plugins: [require('@tailwindcss/forms')]\n}`;\n}\n","\n// Wallet Tools\nimport { GetWalletInfoTool } from \"./wallet/get_wallet_info_tool\";\nimport { GetAccountBalancesTool } from \"./wallet/get_account_balances_tool\";\nimport { SendXRPTool } from \"./wallet/send_xrp_tool\";\nimport { CreateTrustlineTool } from \"./wallet/create_trustline_tool\";\nimport { GetTransactionHistoryTool } from \"./wallet/get_transaction_history_tool\";\nimport { ValidateAddressTool } from \"./wallet/validate_address_tool\";\n\n// RWA Tools \nimport { TokenizeAssetTool } from \"./rwa/tokenize_asset_tool\"\nimport { GetAssetInfoTool } from \"./rwa/get_asset_info_tool\";\n// import { GetRWABalancesTool } from \"./rwa/get_rwa_balances_tool\";\nimport { SendRWATokenTool } from \"./rwa/send_rwa_token_tool\";\nimport { CreateAMMTool } from \"./rwa/create_amm_tool\";\nimport { SwapAMMTool } from \"./rwa/swap_amm_tool\";\nimport { AddLiquidityAMMTool } from \"./rwa/add_liquidity_amm_tool\";\nimport { RemoveLiquidityAMMTool } from \"./rwa/remove_liquidity_amm_tool\";\n\n// Webapp Generation Tools\nimport { GenerateWebappProjectTool } from \"./webapp/generate_webapp_project_tool\";\n\nexport const RWAMcpTools = {\n    // Wallet operations \n    \"GetWalletInfoTool\": GetWalletInfoTool,          // XRPL account data\n    \"GetAccountBalancesTool\": GetAccountBalancesTool,// Real token balances \n    \"SendXRPTool\": SendXRPTool,                      // Real XRP payments\n    \"CreateTrustlineTool\": CreateTrustlineTool,      // Real trustline creation\n    \"GetTransactionHistoryTool\": GetTransactionHistoryTool, // Real transaction data\n    \"ValidateAddressTool\": ValidateAddressTool,      // Real address validation\n\n    // RWA operations\n    \"TokenizeAssetTool\": TokenizeAssetTool,     // Real asset tokenization\n    // \"GetRWABalancesTool\": GetRWABalancesTool,   // Comprehensive RWA portfolio analysis\n    \"GetAssetInfoTool\": GetAssetInfoTool,    // Enhanced asset information with RWA balances\n    \"SendRWATokenTool\": SendRWATokenTool,       // Send RWA tokens to other addresses\n    \n    // AMM operations\n    \"CreateAMMTool\": CreateAMMTool,             // Create Automated Market Maker pools\n    \"SwapAMMTool\": SwapAMMTool,                  // Swap tokens using AMM\n    \"AddLiquidityAMMTool\": AddLiquidityAMMTool,   // Add liquidity to existing AMM pools\n    \"RemoveLiquidityAMMTool\": RemoveLiquidityAMMTool, // Remove liquidity from AMM pools\n    \n    // Webapp Generation\n    \"GenerateWebappProjectTool\": GenerateWebappProjectTool // Generate complete RWA webapp projects\n};\n","import { Client, Wallet, AccountSetAsfFlags, AccountSetTfFlags, xrpToDrops, TrustSet, AccountSet, Payment, convertStringToHex, convertHexToString } from 'xrpl';\nimport { getRWAConfig } from '../config';\nimport { TokenizeAssetInput, TokenizationResult, RWAAsset } from '../types';\nimport { createRWAMemo, findRWATokenizationTx, getColdWallet } from '../utils/xrpl_helpers';\n\nexport class RWAAgent {\n    public client: Client;\n    public wallet: Wallet;\n    public network: 'testnet' | 'mainnet' | 'devnet';\n\n    constructor() {\n        const config = getRWAConfig();\n\n        // Initialize XRPL client\n        this.client = new Client(config.server);\n        this.network = config.network;\n\n        // Initialize wallet from seed/private key\n        this.wallet = Wallet.fromSeed(config.privateKey);\n\n        console.error(`🏗️ RWA Agent initialized on ${this.network}`);\n        console.error(`📍 Wallet address: ${this.wallet.address}`);\n    }\n\n    async connect(): Promise<void> {\n        try {\n            await this.client.connect();\n            console.error('✅ Connected to XRPL');\n        } catch (error) {\n            console.error('❌ Failed to connect to XRPL:', error);\n            throw error;\n        }\n    }\n\n    async disconnect(): Promise<void> {\n        try {\n            await this.client.disconnect();\n            console.error('🔌 Disconnected from XRPL');\n        } catch (error) {\n            console.error('❌ Failed to disconnect:', error);\n        }\n    }\n\n    async getWalletInfo(): Promise<any> {\n        try {\n            const response = await this.client.request({\n                command: 'account_info',\n                account: this.wallet.address,\n                ledger_index: 'validated'\n            });\n            return response.result;\n        } catch (error) {\n            console.error('Failed to get wallet info:', error);\n            throw error;\n        }\n    }\n \n    // Helper method to retrieve asset metadata from transaction history\n    async getAssetMetadataFromMemos(assetId: string): Promise<any> {\n        try {\n            const [currency, issuer] = assetId.split('.');\n\n            // Get transaction history for the issuer\n            const transactions = await this.client.request({\n                command: 'account_tx',\n                account: issuer,\n                limit: 100, // Look through recent transactions\n                ledger_index_min: -1,\n                ledger_index_max: -1\n            });\n\n            // Use helper function to find RWA tokenization transaction\n            return findRWATokenizationTx(transactions.result.transactions, currency);\n\n        } catch (error: any) {\n            console.error('Failed to retrieve asset metadata:', error);\n            return null;\n        }\n    }\n\n    async getAssetInfo(assetId: string): Promise<RWAAsset | null> {\n        try {\n            // First, try to get metadata from memos\n            const metadata = await this.getAssetMetadataFromMemos(assetId);\n\n            if (metadata) {\n                return {\n                    id: assetId,\n                    type: metadata.assetDetails.type,\n                    name: metadata.assetDetails.name,\n                    totalValue: metadata.assetDetails.totalValue,\n                    tokenSymbol: metadata.assetDetails.tokenSymbol,\n                    totalSupply: metadata.assetDetails.totalSupply,\n                    yieldRate: metadata.assetDetails.yieldRate\n                };\n            }\n\n            // Fallback: parse asset ID for basic info\n            const [currency, issuer] = assetId.split('.');\n\n            // Get basic account information\n            const accountInfo = await this.client.request({\n                command: 'account_info',\n                account: issuer,\n                ledger_index: 'validated'\n            });\n\n            // Check if Domain field has metadata URL\n            if (accountInfo.result.account_data.Domain) {\n                const domain = convertHexToString(accountInfo.result.account_data.Domain);\n                console.error(`📍 Domain found for metadata: ${domain}`);\n                // Here you could fetch from the domain URL if needed\n            }\n\n            // Return basic asset information\n            return {\n                id: assetId,\n                type: \"real_estate\", // Would need metadata to determine\n                name: `Asset ${currency}`,\n                totalValue: 0, // Would need metadata to determine\n                tokenSymbol: currency,\n                totalSupply: 0, // Would need to calculate from trustlines\n                yieldRate: 0 // Would need metadata to determine\n            };\n\n        } catch (error: any) {\n            console.error('Failed to get asset info:', error);\n            return null;\n        }\n    }\n\n    // Issue tokens to specific investors\n    // async issueTokensToInvestors(\n    //     assetId: string,\n    //     distributions: Array<{ address: string, amount: number }>\n    // ): Promise<any> {\n    //     try {\n    //         const [currency, issuer] = assetId.split('.');\n    //         const results = [];\n\n    //         console.error(`💰 Issuing ${currency} tokens to ${distributions.length} investors...`);\n\n    //         for (const distribution of distributions) {\n    //             try {\n    //                 const payment: Payment = {\n    //                     TransactionType: 'Payment',\n    //                     Account: this.wallet.address,\n    //                     Destination: distribution.address,\n    //                     Amount: {\n    //                         currency: currency,\n    //                         issuer: this.wallet.address,\n    //                         value: distribution.amount.toString()\n    //                     },\n    //                     Fee: '12'\n    //                 };\n\n    //                 const result = await this.client.submitAndWait(payment, { wallet: this.wallet });\n    //                 results.push({\n    //                     address: distribution.address,\n    //                     amount: distribution.amount,\n    //                     hash: result.result.hash,\n    //                     status: 'success'\n    //                 });\n\n    //                 console.error(`✅ Sent ${distribution.amount} ${currency} to ${distribution.address.substring(0, 8)}...`);\n\n    //             } catch (error: any) {\n    //                 results.push({\n    //                     address: distribution.address,\n    //                     amount: distribution.amount,\n    //                     status: 'failed',\n    //                     error: error.message\n    //                 });\n    //                 console.error(`❌ Failed to send to ${distribution.address}: ${error.message}`);\n    //             }\n    //         }\n\n    //         const successCount = results.filter(r => r.status === 'success').length;\n\n    //         return {\n    //             status: successCount === distributions.length ? 'success' : 'partial',\n    //             message: `Issued tokens to ${successCount}/${distributions.length} investors`,\n    //             distributions: results,\n    //             summary: {\n    //                 total_investors: distributions.length,\n    //                 successful: successCount,\n    //                 failed: distributions.length - successCount,\n    //                 total_tokens_distributed: results\n    //                     .filter(r => r.status === 'success')\n    //                     .reduce((sum, r) => sum + r.amount, 0)\n    //             }\n    //         };\n\n    //     } catch (error: any) {\n    //         throw new Error(`Failed to issue tokens: ${error.message}`);\n    //     }\n    // }\n\n    // Check actual token supply on XRPL\n    async getActualTokenSupply(assetId: string): Promise<{\n        totalIssued: number;\n        holderCount: number;\n        issuerBalance: number;\n        circulatingSupply: number;\n    }> {\n        try {\n            const [currency, issuer] = assetId.split('.');\n\n            // Get all account lines for the issuer\n            const accountLines = await this.client.request({\n                command: 'account_lines',\n                account: issuer,\n                ledger_index: 'validated'\n            });\n\n            let totalIssued = 0;\n            let holderCount = 0;\n            let issuerBalance = 0;\n\n            // Analyze all trustlines for this currency\n            for (const line of accountLines.result.lines) {\n                if (line.currency === currency) {\n                    const balance = Math.abs(parseFloat(line.balance));\n\n                    if (line.account === issuer) {\n                        // This is the issuer's own balance\n                        issuerBalance = balance;\n                    } else if (balance > 0) {\n                        // This is a holder with tokens\n                        totalIssued += balance;\n                        holderCount++;\n                    }\n                }\n            }\n\n            // Calculate circulating supply (tokens not held by issuer)\n            const circulatingSupply = totalIssued;\n\n            return {\n                totalIssued: totalIssued + issuerBalance, // Total tokens created\n                holderCount,\n                issuerBalance, // Tokens still held by issuer\n                circulatingSupply // Tokens held by investors\n            };\n\n        } catch (error: any) {\n            console.error('Failed to get actual token supply:', error);\n            return {\n                totalIssued: 0,\n                holderCount: 0,\n                issuerBalance: 0,\n                circulatingSupply: 0\n            };\n        }\n    }\n\n    // Get token holders list\n    async getTokenHolders(assetId: string): Promise<Array<{\n        address: string;\n        balance: number;\n        percentage: number;\n    }>> {\n        try {\n            const [currency, issuer] = assetId.split('.');\n            const holders = [];\n\n            // Get all accounts that have trustlines to this issuer\n            const accountLines = await this.client.request({\n                command: 'account_lines',\n                account: issuer,\n                ledger_index: 'validated'\n            });\n\n            let totalSupply = 0;\n\n            // First pass: calculate total supply\n            for (const line of accountLines.result.lines) {\n                if (line.currency === currency) {\n                    const balance = Math.abs(parseFloat(line.balance));\n                    if (balance > 0) {\n                        totalSupply += balance;\n                    }\n                }\n            }\n\n            // Second pass: collect holder information\n            for (const line of accountLines.result.lines) {\n                if (line.currency === currency) {\n                    const balance = Math.abs(parseFloat(line.balance));\n                    if (balance > 0) {\n                        holders.push({\n                            address: line.account,\n                            balance: balance,\n                            percentage: totalSupply > 0 ? (balance / totalSupply) * 100 : 0\n                        });\n                    }\n                }\n            }\n\n            // Sort by balance descending\n            return holders.sort((a, b) => b.balance - a.balance);\n\n        } catch (error: any) {\n            console.error('Failed to get token holders:', error);\n            return [];\n        }\n    }\n\n    // Get comprehensive RWA token balances for an account (following XRPL dev portal patterns)\n    async getRWATokenBalances(accountAddress?: string): Promise<{\n        account: string;\n        xrp_balance: number;\n        rwa_tokens: Array<{\n            currency: string;\n            issuer: string;\n            balance: number;\n            asset_id: string;\n            is_rwa_token: boolean;\n            asset_metadata?: any;\n            estimated_value?: number;\n            limit?: string;\n            quality_in?: number;\n            quality_out?: number;\n        }>;\n        total_rwa_value: number;\n        portfolio_summary: any;\n    }> {\n        try {\n            const targetAddress = accountAddress || this.wallet.address;\n\n            // Get XRP balance using account_info (similar to XRPL example pattern)\n            const accountInfo = await this.client.request({\n                command: 'account_info',\n                account: targetAddress,\n                ledger_index: 'validated'\n            });\n            const xrpBalance = Number(accountInfo.result.account_data.Balance) / 1000000;\n\n            // Get all trustlines (token balances) using account_lines (following XRPL pattern)\n            const trustLines = await this.client.request({\n                command: 'account_lines',\n                account: targetAddress,\n                ledger_index: 'validated'\n            });\n\n            const rwaTokens = [];\n            let totalRWAValue = 0;\n\n            // Process each trust line to identify RWA tokens\n            for (const line of trustLines.result.lines) {\n                const assetId = `${line.currency}.${line.account}`;\n                const balance = Math.abs(Number(line.balance));\n\n                // Try to get asset metadata to determine if it's an RWA token\n                let assetMetadata = null;\n                let isRWAToken = false;\n\n                try {\n                    assetMetadata = await this.getAssetMetadataFromMemos(assetId);\n                    isRWAToken = !!assetMetadata;\n                } catch (error) {\n                    console.error(`Could not retrieve metadata for ${assetId}:`, error);\n                }\n\n                // Calculate token value if we have metadata\n                let tokenValue = 0;\n                if (assetMetadata && assetMetadata.assetDetails) {\n                    const pricePerToken = assetMetadata.assetDetails.totalValue / assetMetadata.assetDetails.totalSupply;\n                    tokenValue = balance * pricePerToken;\n                    totalRWAValue += tokenValue;\n                }\n\n                rwaTokens.push({\n                    currency: line.currency,\n                    issuer: line.account,\n                    balance: balance,\n                    asset_id: assetId,\n                    is_rwa_token: isRWAToken,\n                    asset_metadata: assetMetadata,\n                    estimated_value: tokenValue,\n                    limit: line.limit,\n                    quality_in: line.quality_in,\n                    quality_out: line.quality_out\n                });\n            }\n\n            // Generate portfolio summary\n            const rwaTokensOnly = rwaTokens.filter(token => token.is_rwa_token);\n            const portfolioSummary = {\n                total_tokens: rwaTokens.length,\n                confirmed_rwa_tokens: rwaTokensOnly.length,\n                total_estimated_rwa_value: totalRWAValue,\n                xrp_balance: xrpBalance,\n                portfolio_health: xrpBalance >= 10 ? 'Healthy' : 'Low XRP Reserve',\n                diversification: {\n                    real_estate: rwaTokensOnly.filter(t => t.asset_metadata?.assetDetails?.type === 'real_estate').length,\n                    treasury: rwaTokensOnly.filter(t => t.asset_metadata?.assetDetails?.type === 'treasury').length,\n                    commodity: rwaTokensOnly.filter(t => t.asset_metadata?.assetDetails?.type === 'commodity').length,\n                    bond: rwaTokensOnly.filter(t => t.asset_metadata?.assetDetails?.type === 'bond').length\n                }\n            };\n\n            return {\n                account: targetAddress,\n                xrp_balance: xrpBalance,\n                rwa_tokens: rwaTokens,\n                total_rwa_value: totalRWAValue,\n                portfolio_summary: portfolioSummary\n            };\n\n        } catch (error: any) {\n            console.error('Failed to get RWA token balances:', error);\n            throw new Error(`Failed to get RWA token balances: ${error.message}`);\n        }\n    }\n\n    async tokenizeAsset(input: TokenizeAssetInput): Promise<TokenizationResult> {\n        try {\n\n            // Generate currency code from token symbol\n            const currency = input.tokenSymbol.toUpperCase().padEnd(3, '0').substring(0, 3);\n\n            // STEP 1: Create asset metadata object\n            const assetMetadata = {\n                version: \"1.0\",\n                timestamp: Date.now(),\n                assetDetails: {\n                    name: input.name,\n                    type: input.type,\n                    totalValue: input.totalValue,\n                    tokenSymbol: input.tokenSymbol,\n                    totalSupply: input.totalSupply,\n                    yieldRate: input.yieldRate || 0,\n                    pricePerToken: input.totalValue / input.totalSupply\n                },\n                compliance: {\n                    accreditedOnly: input.accreditedOnly || false,\n                    jurisdiction: \"US\",\n                    tokenizationDate: new Date().toISOString()\n                },\n                issuer: {\n                    address: this.wallet.address,\n                    network: this.network\n                }\n            };\n\n            // STEP 2: Create memo with asset metadata using helper function\n            const rwaMemo = createRWAMemo(assetMetadata);\n\n            const coldWallet = getColdWallet()\n\n            // STEP 3: Enable issuing capabilities with metadata memo\n            const accountSet: AccountSet = {\n                TransactionType: 'AccountSet',\n                Account: coldWallet.address,\n                SetFlag: AccountSetAsfFlags.asfDefaultRipple,\n                Flags: (AccountSetTfFlags.tfDisallowXRP | AccountSetTfFlags.tfRequireDestTag),\n                Fee: '12',\n                Memos: [rwaMemo]\n            };\n\n            const accountSetResult = await this.client.submitAndWait(accountSet, { wallet: coldWallet });\n            console.error(`✅ Account set for issuing with metadata: ${accountSetResult.result.hash}`);\n\n            console.error(`🎨 Starting token issuance for ${input.totalSupply} ${currency} tokens...`);\n\n            // Create a trustline to treasury to hold all tokens initially\n            const trustline: TrustSet = {\n                TransactionType: 'TrustSet',\n                Account: this.wallet.address,\n                LimitAmount: {\n                    currency: currency,\n                    issuer: coldWallet.address,\n                    value: input.totalSupply.toString()\n                },\n                Fee: '12'\n            };\n\n            const trustlineResult = await this.client.submitAndWait(trustline, { wallet: this.wallet });\n            console.error(`✅ Trustline created: ${trustlineResult.result.hash}`);\n\n            // Issue all tokens to issuer (this creates the token supply)\n            const issuancePayment: Payment = {\n                TransactionType: 'Payment',\n                Account: coldWallet.address,\n                Destination: this.wallet.address,\n                DestinationTag: 1,\n                Amount: {\n                    currency: currency,\n                    issuer: coldWallet.address,\n                    value: input.totalSupply.toString()\n                },\n                Fee: '12'\n            };\n\n            const issuanceResult = await this.client.submitAndWait(issuancePayment, { wallet: coldWallet });\n            console.error(`✅ ${input.totalSupply} ${currency} tokens issued: ${issuanceResult.result.hash}`);\n\n            let issuanceResults: Array<{ type: string, hash: string, amount: number, destination: string }> = [];\n\n            issuanceResults.push({\n                type: 'trustline_creation',\n                hash: trustlineResult.result.hash,\n                amount: input.totalSupply,\n                destination: this.wallet.address\n            });\n\n            issuanceResults.push({\n                type: 'token_issuance',\n                hash: issuanceResult.result.hash,\n                amount: input.totalSupply,\n                destination: this.wallet.address\n            });\n\n            const tokensIssued = true;\n            console.error(`✨ SUCCESS: ${input.totalSupply} ${currency} tokens now exist on XRPL!`);\n\n            const tokenizationTxHash = accountSetResult.result.hash;\n            const successMessage = `Successfully tokenized and issued ${input.totalSupply} ${currency} tokens for ${input.name}`\n\n            const finalResult: TokenizationResult = {\n                status: 'success',\n                tokenId: `${currency}.${coldWallet.address}`,\n                currency: currency,\n                issuerAddress: coldWallet.address,\n                message: successMessage,\n                metadata: {\n                    assetMetadata,\n                    tokenizationTxHash,\n                    retrievalMethod: \"memo_parsing\",\n                    tokensIssued,\n                    issuanceResults: issuanceResults.length > 0 ? issuanceResults : undefined\n                }\n            };\n\n            return finalResult;\n\n        } catch (error: any) {\n            console.error('Tokenization failed:', error);\n            return {\n                status: 'error',\n                tokenId: '',\n                currency: '',\n                issuerAddress: this.wallet.address,\n                message: `Failed to tokenize asset: ${error.message}`\n            };\n        }\n    }\n}\n"],"mappings":"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","names":["path","config","z","z","z","z","z","z","z","z","z","xrpToDrops","z","xrpToDrops","z","xrpToDrops","z","xrpToDrops","z","config","Wallet","convertHexToString","config","Wallet","convertHexToString"]}