lend and withdraw asset with lulo, not only usdc

This commit is contained in:
zhourunlai
2025-01-02 19:28:56 +08:00
parent 8e2fe87c1c
commit 33737f8bef
13 changed files with 356 additions and 1 deletions

View File

@@ -3,4 +3,5 @@ RPC_URL=
SOLANA_PRIVATE_KEY=
JUPITER_REFERRAL_ACCOUNT=
JUPITER_FEE_BPS=
FLASH_PRIVILEGE= referral | nft | none
FLASH_PRIVILEGE= referral | nft | none
FLEXLEND_API_KEY=

View File

@@ -13,6 +13,8 @@ import stakeWithJupAction from "./jupiter/stakeWithJup";
import stakeWithSolayerAction from "./solayer/stakeWithSolayer";
import registerDomainAction from "./sns/registerDomain";
import lendAssetAction from "./lulo/lendAsset";
import luloLendAction from "./lulo/luloLend";
import luloWithdrawAction from "./lulo/luloWithdraw";
import createGibworkTaskAction from "./gibwork/createGibworkTask";
import resolveSolDomainAction from "./sns/resolveSolDomain";
import pythFetchPriceAction from "./pyth/pythFetchPrice";
@@ -48,6 +50,8 @@ export const ACTIONS = {
STAKE_WITH_SOLAYER_ACTION: stakeWithSolayerAction,
REGISTER_DOMAIN_ACTION: registerDomainAction,
LEND_ASSET_ACTION: lendAssetAction,
LULO_LEND_ACTION: luloLendAction,
LULO_WITHDRAW_ACTION: luloWithdrawAction,
CREATE_GIBWORK_TASK_ACTION: createGibworkTaskAction,
RESOLVE_SOL_DOMAIN_ACTION: resolveSolDomainAction,
PYTH_FETCH_PRICE_ACTION: pythFetchPriceAction,

View File

@@ -0,0 +1,62 @@
import { Action } from "../../types/action";
import { SolanaAgentKit } from "../../agent";
import { z } from "zod";
import { luloLend } from "../../tools/lulo";
const luloLendAction: Action = {
name: "LULO_LEND",
similes: [
"lend USDC with lulo",
"lend PYUSD with lulo",
"lend USDS with lulo",
"lend USDT with lulo",
"lend SQL with lulo",
"lend jitoSQL with lulo",
"lend bSQL with lulo",
"lend mSQL with lulo",
"lend BONK with lulo",
"lend JUP with lulo",
],
description: "Lend SPL tokens using Lulo protocol",
examples: [
[
{
input: {
mintAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
amount: 100,
},
output: {
status: "success",
signature: "4xKpN2...",
message: "Successfully lend 100 USDC",
},
explanation: "Lend 100 USDC on Lulo",
},
],
],
schema: z.object({
mintAddress: z.string().describe("SPL Mint address"),
amount: z.number().positive().describe("Amount to lend"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const mintAddress = input.mintAddress as string;
const amount = input.amount as number;
const response = await luloLend(agent, mintAddress, amount);
return {
status: "success",
signature: response,
message: `Successfully lend ${amount} of token ${mintAddress}`,
};
} catch (error: any) {
return {
status: "error",
message: `Lend failed: ${error.message}`,
};
}
},
};
export default luloLendAction;

View File

@@ -0,0 +1,62 @@
import { Action } from "../../types/action";
import { SolanaAgentKit } from "../../agent";
import { z } from "zod";
import { luloWithdraw } from "../../tools/lulo";
const luloWithdrawAction: Action = {
name: "LULO_WITHDRAW",
similes: [
"withdraw USDC with lulo",
"withdraw PYUSD with lulo",
"withdraw USDS with lulo",
"withdraw USDT with lulo",
"withdraw SQL with lulo",
"withdraw jitoSQL with lulo",
"withdraw bSQL with lulo",
"withdraw mSQL with lulo",
"withdraw BONK with lulo",
"withdraw JUP with lulo",
],
description: "Withdraw SPL tokens using Lulo protocol",
examples: [
[
{
input: {
mintAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
amount: 100,
},
output: {
status: "success",
signature: "4xKpN2...",
message: "Successfully withdraw 100 USDC",
},
explanation: "Withdraw 100 USDC on Lulo",
},
],
],
schema: z.object({
mintAddress: z.string().describe("SPL Mint address"),
amount: z.number().positive().describe("Amount to lend"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const mintAddress = input.mintAddress as string;
const amount = input.amount as number;
const response = await luloWithdraw(agent, mintAddress, amount);
return {
status: "success",
signature: response,
message: `Successfully withdraw ${amount} of token ${mintAddress}`,
};
} catch (error: any) {
return {
status: "error",
message: `Withdraw failed: ${error.message}`,
};
}
},
};
export default luloWithdrawAction;

View File

@@ -14,6 +14,8 @@ import {
getPrimaryDomain,
launchPumpFunToken,
lendAsset,
luloLend,
luloWithdraw,
mintCollectionNFT,
openbookCreateMarket,
manifestCreateMarket,
@@ -275,6 +277,14 @@ export class SolanaAgentKit {
return lendAsset(this, amount);
}
async luloLend(mintAddress: string, amount: number): Promise<string> {
return luloLend(this, mintAddress, amount);
}
async luloWithdraw(mintAddress: string, amount: number): Promise<string> {
return luloWithdraw(this, mintAddress, amount);
}
async getTPS(): Promise<number> {
return getTPS(this);
}

View File

@@ -39,6 +39,8 @@ import {
SolanaPumpfunTokenLaunchTool,
SolanaCreateImageTool,
SolanaLendAssetTool,
SolanaLuloLendTool,
SolanaLuloWithdrawTool,
SolanaTPSCalculatorTool,
SolanaStakeTool,
SolanaRestakeTool,
@@ -100,6 +102,8 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
new SolanaPumpfunTokenLaunchTool(solanaKit),
new SolanaCreateImageTool(solanaKit),
new SolanaLendAssetTool(solanaKit),
new SolanaLuloLendTool(solanaKit),
new SolanaLuloWithdrawTool(solanaKit),
new SolanaTPSCalculatorTool(solanaKit),
new SolanaStakeTool(solanaKit),
new SolanaRestakeTool(solanaKit),

View File

@@ -1 +1,3 @@
export * from "./lend_asset";
export * from "./lulo_lend";
export * from "./lulo_withdraw";

View File

@@ -0,0 +1,37 @@
import { Tool } from "langchain/tools";
import { SolanaAgentKit } from "../../agent";
export class SolanaLuloLendTool extends Tool {
name = "solana_lulo_lend";
description = `Lend token for yield using Lulo. (support USDC/PYUSD/USDS/USDT/SOL/jitoSOL/bSOL/mSOL/BONK/JUP)
Inputs:
mintAddress: string, eg "So11111111111111111111111111111111111111112" (required)
amount: number, eg 1, 0.01 (required)`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
async _call(input: string): Promise<string> {
try {
const parsedInput = JSON.parse(input);
const mintAddress = parsedInput.mintAddress
const amount = parsedInput.amount;
const tx = await this.solanaKit.luloLend(mintAddress, amount);
return JSON.stringify({
status: "success",
message: "Asset lent successfully",
transaction: tx,
amount,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}

View File

@@ -0,0 +1,37 @@
import { Tool } from "langchain/tools";
import { SolanaAgentKit } from "../../agent";
export class SolanaLuloWithdrawTool extends Tool {
name = "solana_lulo_withdraw";
description = `Withdraw token USDC using Lulo. (support USDC/PYUSD/USDS/USDT/SOL/jitoSOL/bSOL/mSOL/BONK/JUP)
Inputs (input is a json string):
mintAddress: string, eg "So11111111111111111111111111111111111111112" (required)
amount: number, eg 1, 0.01 (required)`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
async _call(input: string): Promise<string> {
try {
const parsedInput = JSON.parse(input);
const mintAddress = parsedInput.mintAddress
const amount = parsedInput.amount;
const tx = await this.solanaKit.luloWithdraw(mintAddress, amount);
return JSON.stringify({
status: "success",
message: "Asset withdraw successfully",
transaction: tx,
amount,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}

View File

@@ -1 +1,3 @@
export * from "./lend";
export * from "./lulo_lend";
export * from "./lulo_withdraw";

View File

@@ -0,0 +1,64 @@
import { VersionedTransaction } from "@solana/web3.js";
import { SolanaAgentKit } from "../../index";
/**
* Lend tokens for yields using Lulo
* @param agent SolanaAgentKit instance
* @param mintAddress SPL Mint address
* @param amount Amount to lend
* @returns Transaction signature
*/
export async function luloLend(
agent: SolanaAgentKit,
mintAddress: string,
amount: number,
): Promise<string> {
try {
const response = await fetch(
`https://api.flexlend.fi/generate/account/deposit?priorityFee=50000`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-wallet-pubkey": agent.wallet.publicKey.toBase58(),
"x-api-key": process.env.FLEXLEND_API_KEY!
},
body: JSON.stringify({
owner: agent.wallet.publicKey.toBase58(),
mintAddress: mintAddress,
depositAmount: amount.toString(),
}),
},
);
const { data: { transactionMeta } } = await response.json()
// Deserialize the transaction
const luloTxn = VersionedTransaction.deserialize(
Buffer.from(transactionMeta[0].transaction, "base64"),
);
// Get a recent blockhash and set it
const { blockhash } = await agent.connection.getLatestBlockhash();
luloTxn.message.recentBlockhash = blockhash;
// Sign and send transaction
luloTxn.sign([agent.wallet]);
const signature = await agent.connection.sendTransaction(luloTxn, {
preflightCommitment: "confirmed",
maxRetries: 3,
});
// Wait for confirmation using the latest strategy
const latestBlockhash = await agent.connection.getLatestBlockhash();
await agent.connection.confirmTransaction({
signature,
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
});
return signature;
} catch (error: any) {
throw new Error(`Lending failed: ${error.message}`);
}
}

View File

@@ -0,0 +1,69 @@
import { VersionedTransaction } from "@solana/web3.js";
import { SolanaAgentKit } from "../../index";
/**
* Withdraw tokens for yields using Lulo
* @param agent SolanaAgentKit instance
* @param mintAddress SPL Mint address
* @param amount Amount to withdraw
* @returns Transaction signature
*/
export async function luloWithdraw(
agent: SolanaAgentKit,
mintAddress: string,
amount: number,
): Promise<string> {
try {
if (!agent.config.FLEXLEND_API_KEY) {
throw new Error("Lulo API key not found in agent configuration");
}
const response = await fetch(
`https://api.flexlend.fi/generate/account/withdraw?priorityFee=50000`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-wallet-pubkey": agent.wallet.publicKey.toBase58(),
"x-api-key": agent.config.FLEXLEND_API_KEY
},
body: JSON.stringify({
owner: agent.wallet.publicKey.toBase58(),
mintAddress: mintAddress,
depositAmount: amount,
}),
},
);
const { data: { transactionMeta } } = await response.json()
// Deserialize the transaction
const luloTxn = VersionedTransaction.deserialize(
Buffer.from(transactionMeta[0].transaction, "base64"),
);
// Get a recent blockhash and set it
const { blockhash } = await agent.connection.getLatestBlockhash();
luloTxn.message.recentBlockhash = blockhash;
// Sign and send transaction
luloTxn.sign([agent.wallet]);
const signature = await agent.connection.sendTransaction(luloTxn, {
preflightCommitment: "confirmed",
maxRetries: 3,
});
// Wait for confirmation using the latest strategy
const latestBlockhash = await agent.connection.getLatestBlockhash();
await agent.connection.confirmTransaction({
signature,
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
});
return signature;
} catch (error: any) {
throw new Error(`Lending failed: ${error.message}`);
}
}

View File

@@ -7,6 +7,7 @@ export interface Config {
JUPITER_REFERRAL_ACCOUNT?: string;
JUPITER_FEE_BPS?: number;
FLASH_PRIVILEGE?: string;
FLEXLEND_API_KEY?: string;
}
export interface Creator {