BORROW
Borrow tokens from a BAMM position by providing the contract address and amount. Optionally specify the token address and symbol for accuracy.
Instructions
Borrow tokens from a BAMM position
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| bammAddress | Yes | The address of the BAMM contract | |
| amount | Yes | The amount to borrow | |
| borrowToken | No | The address of the token to borrow | |
| borrowTokenSymbol | No | The symbol of the token to borrow (e.g., 'IQT') |
Implementation Reference
- src/tools/borrow.ts:28-76 (handler)Main tool definition for BORROW. Defines the tool name, description, Zod schema (parameters), and the execute handler which instantiates WalletService and BorrowService, calls borrowService.execute(), and returns a formatted success/error message.
export const borrowTool: Tool<FastMCPSessionAuth, typeof borrowToolParams> = { name: "BORROW", description: "Borrow tokens from a BAMM position", parameters: borrowToolParams, 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 borrowService = new BorrowService(walletService); const result = await borrowService.execute({ bammAddress: params.bammAddress as Address, borrowToken: params.borrowToken as Address | undefined, borrowTokenSymbol: params.borrowTokenSymbol, amount: params.amount, }); return dedent` ✅ Borrowing Successful 🌐 BAMM Address: ${params.bammAddress} 💸 Amount: ${formatNumber(Number(params.amount))} 🪙 Token: ${params.borrowTokenSymbol ?? params.borrowToken} 🔗 Transaction: ${result.txHash} Tokens have been borrowed from your BAMM position. `; } catch (error) { if (error instanceof Error) { return dedent` ❌ Borrowing Failed Error: ${error.message} Please verify your inputs and try again. `; } return "An unknown error occurred while borrowing tokens"; } }, }; - src/tools/borrow.ts:9-24 (schema)Zod schema for BORROW tool parameters: bammAddress (required, hex address), amount (required string), borrowToken (optional hex address), borrowTokenSymbol (optional string).
const borrowToolParams = 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 borrow"), borrowToken: z .string() .regex(/^0x[a-fA-F0-9]{40}$/) .optional() .describe("The address of the token to borrow"), borrowTokenSymbol: z .string() .optional() .describe("The symbol of the token to borrow (e.g., 'IQT')"), }); - src/index.ts:19-20 (registration)Registration of the BORROW tool on the FastMCP server via server.addTool(borrowTool).
server.addTool(addCollateralTool); server.addTool(borrowTool); - src/services/borrow.ts:9-118 (helper)BorrowService class with the execute() method that performs the actual borrowing logic: resolves token address from symbol, validates token against BAMM, checks balance, ensures token approval, calculates rent, builds the action struct, and submits the transaction via the wallet client.
export interface BorrowParams { bammAddress: Address; borrowToken?: Address; borrowTokenSymbol?: string; amount: string; } export class BorrowService { constructor(private walletService: WalletService) {} async execute(params: BorrowParams): Promise<{ txHash: string }> { let { bammAddress, borrowToken, borrowTokenSymbol, amount } = params; if (!borrowToken && !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, ); const collateralBalance: bigint = await publicClient.readContract({ address: borrowToken, abi: erc20Abi, functionName: "balanceOf", args: [userAddress], }); if (collateralBalance < amountInWei) { throw new Error("Insufficient collateral token balance"); } 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 rent based on borrowed amount and rentedMultiplier const rent = (amountInWei * rentedMultiplier) / BigInt(1e18); 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: rent, 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 in borrow service", error); throw error; } } } - src/lib/templates.ts:83-86 (helper)BORROW_TEMPLATE - a prompt template for the LLM to extract borrowing parameters, derived from TOKEN_OPERATION_TEMPLATE.
export const BORROW_TEMPLATE = TOKEN_OPERATION_TEMPLATE.replace( /{{operation}}/g, "borrowing", ).replace(/{{tokenType}}/g, "borrowToken");