sei-agent-kit
Version:
A package for building AI agents on the SEI blockchain
105 lines • 4.49 kB
JavaScript
import { parseUnits, formatUnits, } from 'viem';
import { getTokenDecimals } from '../../utils/getTokenDecimals';
import { sei } from 'viem/chains';
import { comptrollerAbi } from './abi/borrow/controllerabi';
import { tTokenAbi } from './abi/borrow/t_Tokenabi';
import { erc20Abi } from './abi/borrow/erc20abi';
import { getTakaraTTokenAddress } from './tokenMap';
/**
* Borrows underlying tokens from Takara Protocol using the tToken as collateral
* This function assumes you have already supplied collateral by minting tTokens
* @param agent SeiAgentKit instance
* @param params Parameters for borrowing
* @returns Transaction hash and borrowed amount
*/
export async function borrowTakara(agent, { ticker, borrowAmount }) {
console.log(`Borrowing ${borrowAmount} ${ticker} from Takara...`);
const tTokenAddress = getTakaraTTokenAddress(ticker);
if (!tTokenAddress) {
throw new Error(`Invalid ticker: ${ticker}`);
}
const comptrollerAddress = '0x71034bf5eC0FAd7aEE81a213403c8892F3d8CAeE';
// 1. Get the underlying token address from the tToken contract
const underlyingTokenAddress = await agent.publicClient.readContract({
address: tTokenAddress,
abi: tTokenAbi,
functionName: 'underlying',
});
// 2. Get the decimals of the underlying token
const tokenDecimals = await getTokenDecimals(agent, underlyingTokenAddress);
// 3. Convert the borrow amount to the proper decimal representation
const borrowAmountRaw = parseUnits(borrowAmount, tokenDecimals);
// 4. Check the available liquidity in the market
const availableLiquidity = await agent.publicClient.readContract({
address: tTokenAddress,
abi: tTokenAbi,
functionName: 'getCash',
});
// Ensure there's enough liquidity to borrow
if (availableLiquidity < borrowAmountRaw) {
throw new Error(`Insufficient liquidity in market. Requested: ${borrowAmount}, Available: ${formatUnits(availableLiquidity, tokenDecimals)}`);
}
// 5. Attempt to enter markets regardless of current status
const account = agent.walletClient.account;
if (!account) {
throw new Error("Wallet account is not initialized");
}
// Always enter markets to ensure we're in (skip the checkMembership check)
const enterMarketsHash = await agent.walletClient.writeContract({
chain: sei,
account,
address: comptrollerAddress,
abi: comptrollerAbi,
functionName: 'enterMarkets',
args: [[tTokenAddress]],
});
// Wait for the enterMarkets transaction to be mined
const enterMarketReceipt = await agent.publicClient.waitForTransactionReceipt({
hash: enterMarketsHash
});
if (enterMarketReceipt.status !== 'success') {
throw new Error(`Failed to enter markets. Transaction failed: ${enterMarketsHash}`);
}
// Add a short delay to allow any indexing/state updates to complete
await new Promise(resolve => setTimeout(resolve, 2000));
// 6. Get current borrow balance
const { result: currentBorrowBalance } = await agent.publicClient.simulateContract({
address: tTokenAddress,
abi: tTokenAbi,
functionName: 'borrowBalanceCurrent',
args: [agent.wallet_address],
});
// 7. Borrow the tokens
const borrowTxHash = await agent.walletClient.writeContract({
chain: sei,
account,
address: tTokenAddress,
abi: tTokenAbi,
functionName: 'borrow',
args: [borrowAmountRaw],
});
// 8. Wait for the borrow transaction to be mined
const receipt = await agent.publicClient.waitForTransactionReceipt({
hash: borrowTxHash
});
// Check if transaction was successful
if (receipt.status !== 'success') {
throw new Error(`Borrow transaction failed. Hash: ${borrowTxHash}`);
}
// 9. Verify the underlying token balance after borrowing
const tokenBalance = await agent.publicClient.readContract({
address: underlyingTokenAddress,
abi: erc20Abi,
functionName: 'balanceOf',
args: [agent.wallet_address],
});
// 10. Get the updated borrow balance
const { result: updatedBorrowBalance } = await agent.publicClient.simulateContract({
address: tTokenAddress,
abi: tTokenAbi,
functionName: 'borrowBalanceCurrent',
args: [agent.wallet_address],
});
return borrowTxHash;
}
//# sourceMappingURL=borrow.js.map