mirror of
https://github.com/d0zingcat/solana-agent-kit.git
synced 2026-05-14 07:26:46 +00:00
feat: drift vault actions
This commit is contained in:
65
src/actions/drift/createVault.ts
Normal file
65
src/actions/drift/createVault.ts
Normal 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;
|
||||
54
src/actions/drift/depositIntoVault.ts
Normal file
54
src/actions/drift/depositIntoVault.ts
Normal 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;
|
||||
54
src/actions/drift/requestWithdrawalFromVault.ts
Normal file
54
src/actions/drift/requestWithdrawalFromVault.ts
Normal 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;
|
||||
114
src/actions/drift/tradeDelegatedDriftVault.ts
Normal file
114
src/actions/drift/tradeDelegatedDriftVault.ts
Normal 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;
|
||||
76
src/actions/drift/updateVault.ts
Normal file
76
src/actions/drift/updateVault.ts
Normal 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;
|
||||
52
src/actions/drift/withdrawFromVault.ts
Normal file
52
src/actions/drift/withdrawFromVault.ts
Normal 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;
|
||||
@@ -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";
|
||||
|
||||
@@ -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: [
|
||||
[
|
||||
{
|
||||
|
||||
@@ -165,8 +165,8 @@ export async function createVault(
|
||||
.mul(PERCENTAGE_PRECISION)
|
||||
.div(new BN(100))
|
||||
.toNumber(),
|
||||
minDepositAmount: new BN(params.minDepositAmount).mul(spotPrecision),
|
||||
redeemPeriod: new BN(params.redeemPeriod),
|
||||
minDepositAmount: numberToSafeBN(params.minDepositAmount, spotPrecision),
|
||||
redeemPeriod: new BN(params.redeemPeriod * 86400),
|
||||
maxTokens: new BN(params.maxTokens).mul(spotPrecision),
|
||||
managementFee: new BN(params.managementFee)
|
||||
.mul(PERCENTAGE_PRECISION)
|
||||
@@ -214,7 +214,11 @@ export async function updateVault(
|
||||
const vaultDetails = await vaultClient.getVault(vaultPublicKey);
|
||||
|
||||
const tx = await vaultClient.managerUpdateVault(vaultPublicKey, {
|
||||
redeemPeriod: new BN(params.redeemPeriod ?? vaultDetails.redeemPeriod),
|
||||
redeemPeriod: new BN(
|
||||
params.redeemPeriod
|
||||
? params.redeemPeriod * 86400
|
||||
: vaultDetails.redeemPeriod,
|
||||
),
|
||||
maxTokens: new BN(params.maxTokens ?? vaultDetails.maxTokens),
|
||||
minDepositAmount: new BN(
|
||||
params.minDepositAmount ?? vaultDetails.minDepositAmount,
|
||||
@@ -326,7 +330,10 @@ export async function requestWithdrawalFromVault(
|
||||
@param vault Vault address
|
||||
@returns Promise<anchor.Web3.TransactionSignature> - The transaction signature of the redemption
|
||||
*/
|
||||
export async function withdraw(agent: SolanaAgentKit, vault: string) {
|
||||
export async function withdrawFromDriftVault(
|
||||
agent: SolanaAgentKit,
|
||||
vault: string,
|
||||
) {
|
||||
try {
|
||||
const { vaultClient } = initClients(agent);
|
||||
const vaultPublicKey = new PublicKey(vault);
|
||||
@@ -353,7 +360,7 @@ export async function withdraw(agent: SolanaAgentKit, vault: string) {
|
||||
@param vault Vault address
|
||||
@returns Promise<boolean> - Whether the vault is owned by the user
|
||||
*/
|
||||
export async function getIsOwned(agent: SolanaAgentKit, vault: string) {
|
||||
async function getIsOwned(agent: SolanaAgentKit, vault: string) {
|
||||
try {
|
||||
const { vaultClient } = initClients(agent);
|
||||
const vaultPublicKey = new PublicKey(vault);
|
||||
@@ -375,13 +382,13 @@ export async function getIsOwned(agent: SolanaAgentKit, vault: string) {
|
||||
@param type Type of trade (e.g. "market" or "limit")
|
||||
@param vault Vault address
|
||||
*/
|
||||
export async function trade(
|
||||
export async function tradeDriftVault(
|
||||
agent: SolanaAgentKit,
|
||||
vault: string,
|
||||
amount: number,
|
||||
symbol: string,
|
||||
action: "buy" | "sell",
|
||||
type: "market" | "limit",
|
||||
vault: string,
|
||||
price?: number,
|
||||
) {
|
||||
try {
|
||||
|
||||
@@ -50,3 +50,5 @@ export * from "./flash_open_trade";
|
||||
export * from "./flash_close_trade";
|
||||
|
||||
export * from "./create_3land_collectible";
|
||||
|
||||
export * from "./drift_vault";
|
||||
|
||||
Reference in New Issue
Block a user