REPAY
Repay borrowed tokens to a BAMM position on Fraxtal. Provide BAMM address and amount to reduce debt.
Instructions
Repay borrowed tokens to a BAMM position
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| bammAddress | Yes | The address of the BAMM contract | |
| amount | Yes | The amount to repay | |
| borrowToken | No | The address of the token to repay | |
| borrowTokenSymbol | No | The symbol of the token to repay (e.g., 'IQT') |
Implementation Reference
- src/tools/repay.ts:28-76 (handler)The tool handler definition for 'REPAY'. Contains the name, description, Zod schema parameters, and execute function that delegates to RepayService.
export const repayTool: Tool<FastMCPSessionAuth, typeof repayToolParams> = { name: "REPAY", description: "Repay borrowed tokens to a BAMM position", parameters: repayToolParams, execute: async (params, _context) => { try { if (!params.borrowToken && !params.borrowTokenSymbol) { return "Error: Either borrowToken address or borrowTokenSymbol is required"; } const privateKey = process.env.WALLET_PRIVATE_KEY; if (!privateKey) { return "Error: WALLET_PRIVATE_KEY environment variable is not set. Please set it with your wallet's private key (without 0x prefix)."; } const walletService = new WalletService(privateKey); const repayService = new RepayService(walletService); const result = await repayService.execute({ bammAddress: params.bammAddress as Address, borrowToken: params.borrowToken as Address | undefined, borrowTokenSymbol: params.borrowTokenSymbol, amount: params.amount, }); return dedent` ✅ Repayment Successful 🌐 BAMM Address: ${params.bammAddress} 💸 Amount: ${formatNumber(Number(params.amount))} 🪙 Token: ${params.borrowTokenSymbol ?? params.borrowToken} 🔗 Transaction: ${result.txHash} Tokens have been repaid to your BAMM position. `; } catch (error) { if (error instanceof Error) { return dedent` ❌ Repayment Failed Error: ${error.message} Please verify your inputs and try again. `; } return "An unknown error occurred while repaying tokens"; } }, }; - src/tools/repay.ts:9-24 (schema)Zod input schema for REPAY tool: requires bammAddress (Ethereum address), amount (string), and optionally borrowToken (address) or borrowTokenSymbol (e.g., 'IQT').
const repayToolParams = z.object({ bammAddress: z .string() .regex(/^0x[a-fA-F0-9]{40}$/) .describe("The address of the BAMM contract"), amount: z.string().min(1).describe("The amount to repay"), borrowToken: z .string() .regex(/^0x[a-fA-F0-9]{40}$/) .optional() .describe("The address of the token to repay"), borrowTokenSymbol: z .string() .optional() .describe("The symbol of the token to repay (e.g., 'IQT')"), }); - src/services/repay.ts:8-13 (schema)TypeScript interface for RepayParams used by RepayService.execute().
export interface RepayParams { bammAddress: Address; borrowToken?: Address; borrowTokenSymbol?: string; amount: string; } - src/services/repay.ts:15-105 (helper)RepayService class containing the core repayment logic: resolves token address, validates against BAMM, checks balance, ensures approval, reads rentedMultiplier, calculates effectiveRent (negative), and calls executeActions on the BAMM contract.
export class RepayService { constructor(private walletService: WalletService) {} async execute(params: RepayParams): Promise<{ txHash: string }> { let { bammAddress, borrowToken, borrowTokenSymbol, amount } = params; if (!params.borrowToken && !params.borrowTokenSymbol) { throw new Error("Either borrowToken or borrowTokenSymbol is required"); } const publicClient = this.walletService.getPublicClient(); const walletClient = this.walletService.getWalletClient(); if (!walletClient || !walletClient.account) { throw new Error("Wallet client is not initialized"); } const userAddress = walletClient.account.address; const amountInWei = BigInt(Math.floor(Number(amount) * 1e18)); try { if (borrowTokenSymbol) { borrowToken = await getTokenAddressFromSymbol(borrowTokenSymbol); } if (!borrowToken) { throw new Error("Could not resolve borrow token address"); } const tokenValidation = await validateTokenAgainstBAMM( bammAddress, borrowToken, publicClient, ); await checkTokenBalance( borrowToken, userAddress, amountInWei, publicClient, ); await ensureTokenApproval( borrowToken, bammAddress, amountInWei, publicClient, walletClient, ); const rentedMultiplier: bigint = await publicClient.readContract({ address: bammAddress, abi: BAMM_ABI, functionName: "rentedMultiplier", args: [], }); // Calculate effective rent for repayment (negative rent for repayment) const effectiveRent = -(amountInWei * 1_000_000_000_000_000_000n) / rentedMultiplier; const currentTime = Math.floor(Date.now() / 1000); const deadline = BigInt(currentTime + 300); const action = { token0Amount: tokenValidation.isToken0 ? amountInWei : 0n, token1Amount: tokenValidation.isToken1 ? amountInWei : 0n, rent: effectiveRent, to: userAddress, token0AmountMin: 0n, token1AmountMin: 0n, closePosition: false, approveMax: false, v: 0, r: "0x0000000000000000000000000000000000000000000000000000000000000000" as `0x${string}`, s: "0x0000000000000000000000000000000000000000000000000000000000000000" as `0x${string}`, deadline, }; const { request: executeRequest } = await publicClient.simulateContract({ address: bammAddress, abi: BAMM_ABI, functionName: "executeActions", args: [action], account: walletClient.account, }); const txHash = await walletClient.writeContract(executeRequest); await publicClient.waitForTransactionReceipt({ hash: txHash }); return { txHash }; } catch (error) { console.error("Error repaying:", error); throw error; } } } - src/index.ts:9-25 (registration)Registration: imports repayTool from './tools/repay.js' (line 9) and registers it on the MCP server via server.addTool(repayTool) (line 25).
import { repayTool } from "./tools/repay.js"; async function main() { console.log("🚀 Initializing BAMM MCP Server..."); const server = new FastMCP({ name: "BAMM MCP Server", version: "0.0.1", }); server.addTool(addCollateralTool); server.addTool(borrowTool); server.addTool(getPositionsTool); server.addTool(lendTool); server.addTool(poolStatsTool); server.addTool(removeCollateralTool); server.addTool(repayTool);