feat: drift vault actions

This commit is contained in:
michaelessiet
2025-01-10 19:46:42 +01:00
parent b4b36e5adb
commit 315ce64eed
10 changed files with 444 additions and 8 deletions

View File

@@ -0,0 +1,65 @@
import { z } from "zod";
import type { Action } from "../../types";
import type { SolanaAgentKit } from "../..";
import { createVault } from "../../tools/drift_vault";
const createDriftVaultAction: Action = {
name: "CREATE_DRIFT_VAULT",
similes: ["create a drift vault", "open a drift vault", "create vault"],
description:
"Create a new drift vault delegating the agents address as the owner.",
examples: [
[
{
input: {},
output: {
status: "success",
message: "Drift vault created successfully",
signature:
"2nFeP7taii3wGVgrWk4YiLMPmhtu3Zg9iXCUu4zGBDadwunHw8reXFxRWT7khbFsQ9JT3zK4RYDLNDFDRYvM3wJk",
},
explanation: "Create a drift vault",
},
],
],
schema: z.object({
name: z.string().min(5, "Name must be at least 5 characters"),
// regex matches SOL-SPOT
marketName: z.string().regex(/^([A-Za-z0-9]{2,7})-SPOT$/),
redeemPeriod: z.number().int().min(1, "Redeem period must be at least 1"),
maxTokens: z.number().int().min(100, "Max tokens must be at least 100"),
minDepositAmount: z.number().positive(),
managementFee: z.number().positive().max(20),
profitShare: z.number().positive().max(90).optional().default(5),
handleRate: z.number().optional(),
permissioned: z
.boolean()
.optional()
.describe("Should the vault have a whitelist of not"),
}),
handler: async (agent: SolanaAgentKit, input) => {
try {
const tx = await createVault(
agent,
// @ts-expect-error - zod schema validation
{
...input,
},
);
return {
status: "success",
message: "Drift vault created successfully",
signature: tx,
};
} catch (e) {
return {
status: "error",
// @ts-expect-error - e is not a string
message: `Failed to create drift vault: ${e.message}`,
};
}
},
};
export default createDriftVaultAction;

View File

@@ -0,0 +1,54 @@
import { z } from "zod";
import type { Action } from "../../types";
import type { SolanaAgentKit } from "../../agent";
import { depositIntoVault } from "../../tools/drift_vault";
const depositIntoDriftVaultAction: Action = {
name: "DEPOSIT_INTO_DRIFT_VAULT",
description: "Deposit funds into an existing drift vault",
similes: ["deposit into drift vault", "add funds to drift vault"],
examples: [
[
{
input: {
amount: 100,
vaultAddress: "2nFeP7taii3wGVgrWk4YiLMPmhtu3Zg9iXCUu4zGBD",
},
output: {
status: "success",
message: "Funds deposited successfully",
signature:
"2nFeP7taii3wGVgrWk4YiLMPmhtu3Zg9iXCUu4zGBDadwunHw8reXFxRWT7khbFsQ9JT3zK4RYDLNDFDRYvM3wJk",
},
explanation: "Deposit 100 USDC into a drift vault",
},
],
],
schema: z.object({
vaultAddress: z.string(),
amount: z.number().positive(),
}),
handler: async (agent: SolanaAgentKit, input) => {
try {
const tx = await depositIntoVault(
agent,
input.amount as number,
input.vaultAddress as string,
);
return {
status: "success",
message: "Funds deposited successfully",
signature: tx,
};
} catch (e) {
return {
status: "error",
// @ts-expect-error - error message
message: `Failed to deposit funds: ${e.message}`,
};
}
},
};
export default depositIntoDriftVaultAction;

View File

@@ -0,0 +1,54 @@
import { z } from "zod";
import type { Action } from "../../types";
import type { SolanaAgentKit } from "../../agent";
import { requestWithdrawalFromVault } from "../../tools/drift_vault";
const requestWithdrawalFromVaultAction: Action = {
name: "REQUEST_WITHDRAWAL_FROM_DRIFT_VAULT",
description: "Request a withdrawal from an existing drift vault",
similes: ["withdraw from drift vault", "request withdrawal from vault"],
examples: [
[
{
input: {
amount: 100,
vaultAddress: "2nFeP7taii",
},
output: {
status: "success",
message: "Withdrawal request successful",
signature:
"2nFeP7taii3wGVgrWk4YiLMPmhtu3Zg9iXCUu4zGBDadwunHw8reXFxRWT7khbFsQ9JT3zK4RYDLNDFDRYvM3wJk",
},
explanation: "Request a withdrawal of 100 USDC from a drift vault",
},
],
],
schema: z.object({
vaultAddress: z.string(),
amount: z.number().positive(),
}),
handler: async (agent: SolanaAgentKit, input) => {
try {
const tx = await requestWithdrawalFromVault(
agent,
input.amount as number,
input.vaultAddress as string,
);
return {
status: "success",
message: "Withdrawal request successful",
signature: tx,
};
} catch (e) {
return {
status: "error",
// @ts-expect-error - error message
message: `Failed to request withdrawal: ${e.message}`,
};
}
},
};
export default requestWithdrawalFromVaultAction;

View File

@@ -0,0 +1,114 @@
import { z } from "zod";
import type { Action } from "../../types";
import type { SolanaAgentKit } from "../../agent";
import { tradeDriftVault } from "../../tools";
const tradeDelegatedDriftVaultAction: Action = {
name: "TRADE_DELEGATED_DRIFT_VAULT",
similes: [
"trade delegated drift vault",
"trade delegated vault",
"trade vault",
"trade drift vault",
"trade delegated vault",
"trade vault",
"trade drift vault",
"open drift vault trade",
],
description: "Carry out trades in a Drift vault.",
examples: [
[
{
input: {
vaultAddress: "J1S9H3QjnRtBbbuD4HjPV6RpRhwuk4zKbxsnCHuTgh9w",
amount: 100,
symbol: "SOL",
action: "buy",
type: "market",
},
output: {
status: "success",
message: "Trade successful",
transactionId: "7nE9GvcwsqzYxmJLSrYmSB1V1YoJWVK1KWzAcWAzjXkN",
amount: 100,
symbol: "SOL",
action: "buy",
type: "market",
},
explanation: "Buy 100 SOL in the vault",
},
],
[
{
input: {
vaultAddress: "J1S9H3QjnRtBbbuD4HjPV6RpRhwuk4zKbxsnCHuTgh9w",
amount: 50,
symbol: "SOL",
action: "sell",
type: "limit",
price: 200,
},
output: {
status: "success",
message: "Order placed successful",
transactionId: "8nE9GvcwsqzYxmJLSrYmSB1V1YoJWVK1KWzAcWAzjXkM",
amount: 50,
symbol: "SOL",
action: "sell",
type: "limit",
price: 200,
},
explanation: "Sell 50 SOL in the vault at $200",
},
],
],
schema: z.object({
vaultAddress: z.string().describe("Address of the Drift vault to trade in"),
amount: z.number().positive().describe("Amount to trade"),
symbol: z.string().describe("Symbol of the token to trade"),
action: z.enum(["buy", "sell"]).describe("Trade action - buy or sell"),
type: z.enum(["market", "limit"]).describe("Trade type - market or limit"),
price: z.number().positive().optional().describe("Price for limit order"),
}),
handler: async (agent: SolanaAgentKit, input) => {
try {
const params = {
vaultAddress: input.vaultAddress as string,
amount: input.amount as number,
symbol: input.symbol as string,
action: input.action as "buy" | "sell",
type: input.type as "market" | "limit",
price: input.price as number | undefined,
};
// Carry out the trade
const transactionId = await tradeDriftVault(
agent,
params.vaultAddress,
params.amount,
params.symbol,
params.action,
params.type,
params.price,
);
return {
status: "success",
message:
params.type === "limit"
? "Order placed successfully"
: "Trade successful",
transactionId,
...params,
};
} catch (error) {
return {
status: "error",
// @ts-expect-error error is not a string
message: error.message,
};
}
},
};
export default tradeDelegatedDriftVaultAction;

View File

@@ -0,0 +1,76 @@
import { z } from "zod";
import type { Action } from "../../types";
import type { SolanaAgentKit } from "../../agent";
import { updateVault } from "../../tools/drift_vault";
const updateDriftVaultAction: Action = {
name: "UPDATE_DRIFT_VAULT",
similes: ["update a drift vault", "modify a drift vault", "update vault"],
description: "Update an existing drift vault with new settings.",
examples: [
[
{
input: {
redeemPeriod: 30,
maxTokens: 10000,
minDepositAmount: 10,
managementFee: 5,
profitShare: 10,
handleRate: 0.1,
permissioned: false,
vaultAddress: "2nFeP7taii3wGVgrWk4YiLMPmhtu3Zg9iXCUu4zGBD",
},
output: {
status: "success",
message: "Drift vault updated successfully",
signature:
"2nFeP7taii3wGVgrWk4YiLMPmhtu3Zg9iXCUu4zGBDadwunHw8reXFxRWT7khbFsQ9JT3zK4RYDLNDFDRYvM3wJk",
},
explanation: "Update a drift vault",
},
],
],
schema: z.object({
vaultAddress: z.string(),
name: z.string().min(5, "Name must be at least 5 characters"),
// regex matches SOL-SPOT
marketName: z.string().regex(/^([A-Za-z0-9]{2,7})-SPOT$/),
redeemPeriod: z.number().int().min(1, "Redeem period must be at least 1"),
maxTokens: z.number().int().min(100, "Max tokens must be at least 100"),
minDepositAmount: z.number().positive(),
managementFee: z.number().positive().max(20),
profitShare: z.number().positive().max(90).optional().default(5),
handleRate: z.number().optional(),
permissioned: z
.boolean()
.optional()
.describe("Should the vault have a whitelist of not"),
}),
handler: async (agent: SolanaAgentKit, input) => {
try {
const tx = await updateVault(agent, input.vaultAddress, {
hurdleRate: input.hurdleRate,
maxTokens: input.maxTokens,
minDepositAmount: input.minDepositAmount,
profitShare: input.profitShare,
managementFee: input.managementFee,
permissioned: input.permissioned,
redeemPeriod: input.redeemPeriod,
});
return {
status: "success",
message: "Drift vault parameters updated successfully",
signature: tx,
};
} catch (e) {
return {
status: "error",
// @ts-expect-error - error message
message: `Failed to update drift vault: ${e.message}`,
};
}
},
};
export default updateDriftVaultAction;

View File

@@ -0,0 +1,52 @@
import { z } from "zod";
import type { Action } from "../../types";
import type { SolanaAgentKit } from "../../agent";
import { withdrawFromDriftVault } from "../../tools";
const withdrawFromVaultAction: Action = {
name: "WITHDRAW_FROM_DRIFT_VAULT",
description:
"Withdraw funds from a vault given the redemption time has elapsed.",
similes: ["withdraw from drift vault", "redeem funds from vault"],
examples: [
[
{
input: {
vaultAddress: "2nFeP7taii",
},
output: {
status: "success",
message: "Withdrawal successful",
signature:
"2nFeP7taii3wGVgrWk4YiLMPmhtu3Zg9iXCUu4zGBDadwunHw8reXFxRWT7khbFsQ9JT3zK4RYDLNDFDRYvM3wJk",
},
explanation: "Withdraw funds from a drift vault",
},
],
],
schema: z.object({
vaultAddress: z.string(),
}),
handler: async (agent: SolanaAgentKit, input) => {
try {
const tx = await withdrawFromDriftVault(
agent,
input.vaultAddress as string,
);
return {
status: "success",
message: "Withdrawal successful",
signature: tx,
};
} catch (e) {
return {
status: "error",
// @ts-expect-error - error message
message: `Failed to withdraw funds: ${e.message}`,
};
}
},
};
export default withdrawFromVaultAction;

View File

@@ -30,6 +30,12 @@ import launchPumpfunTokenAction from "./launchPumpfunToken";
import getWalletAddressAction from "./getWalletAddress";
import flashOpenTradeAction from "./flashOpenTrade";
import flashCloseTradeAction from "./flashCloseTrade";
import createDriftVaultAction from "./drift/createVault";
import updateDriftVaultAction from "./drift/updateVault";
import depositIntoDriftVaultAction from "./drift/depositIntoVault";
import requestWithdrawalFromVaultAction from "./drift/requestWithdrawalFromVault";
import withdrawFromVaultAction from "./drift/withdrawFromVault";
import tradeDelegatedDriftVaultAction from "./drift/tradeDelegatedDriftVault";
export const ACTIONS = {
WALLET_ADDRESS_ACTION: getWalletAddressAction,
@@ -65,6 +71,12 @@ export const ACTIONS = {
LAUNCH_PUMPFUN_TOKEN_ACTION: launchPumpfunTokenAction,
FLASH_OPEN_TRADE_ACTION: flashOpenTradeAction,
FLASH_CLOSE_TRADE_ACTION: flashCloseTradeAction,
CREATE_DRIFT_VAULT_ACTION: createDriftVaultAction,
UPDATE_DRIFT_VAULT_ACTION: updateDriftVaultAction,
DEPOSIT_INTO_DRIFT_VAULT_ACTION: depositIntoDriftVaultAction,
REQUEST_WITHDRAWAL_FROM_DRIFT_VAULT_ACTION: requestWithdrawalFromVaultAction,
WITHDRAW_FROM_DRIFT_VAULT_ACTION: withdrawFromVaultAction,
TRADE_DELEGATED_DRIFT_VAULT_ACTION: tradeDelegatedDriftVaultAction,
};
export type { Action, ActionExample, Handler } from "../types/action";

View File

@@ -13,7 +13,7 @@ const mintNFTAction: Action = {
"create token",
"add nft to collection",
],
description: `Mint a new NFT in a collection on Solana blockchain.`,
description: "Mint a new NFT in a collection on Solana blockchain.",
examples: [
[
{