fix: drift vault deposits and withdrawals

This commit is contained in:
michaelessiet
2025-01-14 20:33:18 +01:00
parent 4d50d2f260
commit 2f05af13cb
3 changed files with 62 additions and 19 deletions

View File

@@ -56,6 +56,7 @@ Anyone - whether an SF-based AI researcher or a crypto-native builder - can brin
- Pyth Price feeds for fetching Asset Prices - Pyth Price feeds for fetching Asset Prices
- Register/resolve Alldomains - Register/resolve Alldomains
- Perpetuals Trading with Adrena Protocol - Perpetuals Trading with Adrena Protocol
- Drift Vaults, Perps, Lending and Borrowing
- **Solana Blinks** - **Solana Blinks**
- Lending by Lulo (Best APR for USDC) - Lending by Lulo (Best APR for USDC)
@@ -309,6 +310,34 @@ const signature = await agent.closePerpTradeLong({
const { signature } = await agent.closeEmptyTokenAccounts(); const { signature } = await agent.closeEmptyTokenAccounts();
``` ```
### Create a Drift account
Create a drift account with an initial token deposit.
```typescript
const result = await agent.createDriftUserAccount()
```
### Create a Drift Vault
Create a drift vault.
```typescript
const signature = await agent.createDriftVault({
name: "my-drift-vault",
marketName: "USDC-SPOT",
redeemPeriod: 1, // in days
maxTokens: 100000, // in token units e.g 100000 USDC
minDepositAmount: 5, // in token units e.g 5 USDC
managementFee: 1, // 1%
profitShare: 10, // 10%
hurdleRate: 5, // 5%
permissioned: false, // public vault or whitelist
})
```
### Deposit into a Drift Vault
## Examples ## Examples
### LangGraph Multi-Agent System ### LangGraph Multi-Agent System

View File

@@ -2,8 +2,6 @@ import { z } from "zod";
import type { Action } from "../../types"; import type { Action } from "../../types";
import { getVaultInfo } from "../../tools"; import { getVaultInfo } from "../../tools";
import type { SolanaAgentKit } from "../../agent"; import type { SolanaAgentKit } from "../../agent";
import { decodeName } from "@drift-labs/vaults-sdk";
import { MainnetSpotMarkets, PERCENTAGE_PRECISION } from "@drift-labs/sdk";
const vaultInfoAction: Action = { const vaultInfoAction: Action = {
name: "DRIFT_VAULT_INFO", name: "DRIFT_VAULT_INFO",
@@ -13,7 +11,7 @@ const vaultInfoAction: Action = {
[ [
{ {
input: { input: {
vaultName: "test-vault", vaultNameOrAddress: "test-vault",
}, },
output: { output: {
status: "success", status: "success",
@@ -35,11 +33,11 @@ const vaultInfoAction: Action = {
], ],
], ],
schema: z.object({ schema: z.object({
vaultName: z.string(), vaultNameOrAddress: z.string().describe("Name or address of the vault"),
}), }),
handler: async (agent: SolanaAgentKit, input) => { handler: async (agent: SolanaAgentKit, input) => {
try { try {
const vaultInfo = await getVaultInfo(agent, input.vaultName as string); const vaultInfo = await getVaultInfo(agent, input.vaultNameOrAddress);
return { return {
status: "success", status: "success",

View File

@@ -19,6 +19,7 @@ import {
import { import {
VaultAccount, VaultAccount,
WithdrawUnit, WithdrawUnit,
decodeName,
encodeName, encodeName,
getVaultAddressSync, getVaultAddressSync,
getVaultDepositorAddressSync, getVaultDepositorAddressSync,
@@ -65,9 +66,13 @@ async function getOrCreateVaultDepositor(agent: SolanaAgentKit, vault: string) {
return vaultDepositor; return vaultDepositor;
} catch (e) { } catch (e) {
// @ts-expect-error - error message is a string // @ts-expect-error - error message is a string
if (e.message === "Account not found") { if (e.message.includes("Account does not exist")) {
await vaultClient.initializeVaultDepositor(vaultDepositor); await vaultClient.initializeVaultDepositor(
vaultPublicKey,
agent.wallet.publicKey,
);
} }
await new Promise((resolve) => setTimeout(resolve, 2000));
await cleanUp(); await cleanUp();
return vaultDepositor; return vaultDepositor;
} }
@@ -280,18 +285,29 @@ export async function updateVault(
} }
} }
export const validateAndEncodeAddress = (input: string, programId: string) => {
try {
return new PublicKey(input);
} catch {
return getVaultAddressSync(new PublicKey(programId), encodeName(input));
}
};
/** /**
* Get information on a particular vault given its name * Get information on a particular vault given its name
* @param agent * @param agent
* @param vaultName * @param vaultNameOrAddress
* @returns * @returns
*/ */
export async function getVaultInfo(agent: SolanaAgentKit, vaultName: string) { export async function getVaultInfo(
agent: SolanaAgentKit,
vaultNameOrAddress: string,
) {
try { try {
const { vaultClient, cleanUp } = await initClients(agent); const { vaultClient, cleanUp } = await initClients(agent);
const vaultPublicKey = getVaultAddressSync( const vaultPublicKey = validateAndEncodeAddress(
vaultClient.program.programId, vaultNameOrAddress,
encodeName(vaultName), vaultClient.program.programId.toBase58(),
); );
const [vaultDetails, vaultBalance] = await Promise.all([ const [vaultDetails, vaultBalance] = await Promise.all([
vaultClient.getVault(vaultPublicKey), vaultClient.getVault(vaultPublicKey),
@@ -302,7 +318,7 @@ export async function getVaultInfo(agent: SolanaAgentKit, vaultName: string) {
const spotToken = MainnetSpotMarkets[vaultDetails.spotMarketIndex]; const spotToken = MainnetSpotMarkets[vaultDetails.spotMarketIndex];
const data = { const data = {
name: vaultName, name: decodeName(vaultDetails.name),
delegate: vaultDetails.delegate.toBase58(), delegate: vaultDetails.delegate.toBase58(),
address: vaultPublicKey.toBase58(), address: vaultPublicKey.toBase58(),
marketName: `${spotToken.symbol}-SPOT`, marketName: `${spotToken.symbol}-SPOT`,
@@ -346,9 +362,10 @@ export async function depositIntoVault(
try { try {
const vaultPublicKey = new PublicKey(vault); const vaultPublicKey = new PublicKey(vault);
const [isOwned, vaultDetails] = await Promise.all([ const [isOwned, vaultDetails, vaultDepositor] = await Promise.all([
getIsOwned(agent, vault), getIsOwned(agent, vault),
vaultClient.getVault(vaultPublicKey), vaultClient.getVault(vaultPublicKey),
getOrCreateVaultDepositor(agent, vault),
]); ]);
const spotMarket = driftClient.getSpotMarketAccount( const spotMarket = driftClient.getSpotMarketAccount(
vaultDetails.spotMarketIndex, vaultDetails.spotMarketIndex,
@@ -365,7 +382,6 @@ export async function depositIntoVault(
return await vaultClient.managerDeposit(vaultPublicKey, amountBN); return await vaultClient.managerDeposit(vaultPublicKey, amountBN);
} }
const vaultDepositor = await getOrCreateVaultDepositor(agent, vault);
const tx = await vaultClient.deposit(vaultDepositor, amountBN); const tx = await vaultClient.deposit(vaultDepositor, amountBN);
await cleanUp(); await cleanUp();
@@ -396,7 +412,7 @@ export async function requestWithdrawalFromVault(
if (isOwned) { if (isOwned) {
return await vaultClient.managerRequestWithdraw( return await vaultClient.managerRequestWithdraw(
vaultPublicKey, vaultPublicKey,
new BN(amount.toFixed(0)), numberToSafeBN(amount, QUOTE_PRECISION),
WithdrawUnit.TOKEN, WithdrawUnit.TOKEN,
); );
} }
@@ -405,7 +421,7 @@ export async function requestWithdrawalFromVault(
const tx = await vaultClient.requestWithdraw( const tx = await vaultClient.requestWithdraw(
vaultDepositor, vaultDepositor,
new BN(amount.toFixed(0)), numberToSafeBN(amount, QUOTE_PRECISION),
WithdrawUnit.TOKEN, WithdrawUnit.TOKEN,
); );