mirror of
https://github.com/d0zingcat/solana-agent-kit.git
synced 2026-06-15 15:12:15 +00:00
fix: drift vault deposits and withdrawals
This commit is contained in:
33
README.md
33
README.md
@@ -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
|
||||
- Register/resolve Alldomains
|
||||
- Perpetuals Trading with Adrena Protocol
|
||||
- Drift Vaults, Perps, Lending and Borrowing
|
||||
|
||||
- **Solana Blinks**
|
||||
- Lending by Lulo (Best APR for USDC)
|
||||
@@ -309,6 +310,34 @@ const signature = await agent.closePerpTradeLong({
|
||||
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
|
||||
|
||||
### LangGraph Multi-Agent System
|
||||
@@ -357,7 +386,7 @@ Refer to [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines on how to co
|
||||
|
||||
Apache-2 License
|
||||
|
||||
## Funding
|
||||
## Funding
|
||||
|
||||
If you wanna give back any tokens or donations to the OSS community -- The Public Solana Agent Kit Treasury Address:
|
||||
|
||||
@@ -365,4 +394,4 @@ Solana Network : EKHTbXpsm6YDgJzMkFxNU1LNXeWcUW7Ezf8mjUNQQ4Pa
|
||||
|
||||
## Security
|
||||
|
||||
This toolkit handles private keys and transactions. Always ensure you're using it in a secure environment and never share your private keys.
|
||||
This toolkit handles private keys and transactions. Always ensure you're using it in a secure environment and never share your private keys.
|
||||
|
||||
@@ -2,8 +2,6 @@ import { z } from "zod";
|
||||
import type { Action } from "../../types";
|
||||
import { getVaultInfo } from "../../tools";
|
||||
import type { SolanaAgentKit } from "../../agent";
|
||||
import { decodeName } from "@drift-labs/vaults-sdk";
|
||||
import { MainnetSpotMarkets, PERCENTAGE_PRECISION } from "@drift-labs/sdk";
|
||||
|
||||
const vaultInfoAction: Action = {
|
||||
name: "DRIFT_VAULT_INFO",
|
||||
@@ -13,7 +11,7 @@ const vaultInfoAction: Action = {
|
||||
[
|
||||
{
|
||||
input: {
|
||||
vaultName: "test-vault",
|
||||
vaultNameOrAddress: "test-vault",
|
||||
},
|
||||
output: {
|
||||
status: "success",
|
||||
@@ -35,11 +33,11 @@ const vaultInfoAction: Action = {
|
||||
],
|
||||
],
|
||||
schema: z.object({
|
||||
vaultName: z.string(),
|
||||
vaultNameOrAddress: z.string().describe("Name or address of the vault"),
|
||||
}),
|
||||
handler: async (agent: SolanaAgentKit, input) => {
|
||||
try {
|
||||
const vaultInfo = await getVaultInfo(agent, input.vaultName as string);
|
||||
const vaultInfo = await getVaultInfo(agent, input.vaultNameOrAddress);
|
||||
|
||||
return {
|
||||
status: "success",
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
import {
|
||||
VaultAccount,
|
||||
WithdrawUnit,
|
||||
decodeName,
|
||||
encodeName,
|
||||
getVaultAddressSync,
|
||||
getVaultDepositorAddressSync,
|
||||
@@ -65,9 +66,13 @@ async function getOrCreateVaultDepositor(agent: SolanaAgentKit, vault: string) {
|
||||
return vaultDepositor;
|
||||
} catch (e) {
|
||||
// @ts-expect-error - error message is a string
|
||||
if (e.message === "Account not found") {
|
||||
await vaultClient.initializeVaultDepositor(vaultDepositor);
|
||||
if (e.message.includes("Account does not exist")) {
|
||||
await vaultClient.initializeVaultDepositor(
|
||||
vaultPublicKey,
|
||||
agent.wallet.publicKey,
|
||||
);
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
await cleanUp();
|
||||
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
|
||||
* @param agent
|
||||
* @param vaultName
|
||||
* @param vaultNameOrAddress
|
||||
* @returns
|
||||
*/
|
||||
export async function getVaultInfo(agent: SolanaAgentKit, vaultName: string) {
|
||||
export async function getVaultInfo(
|
||||
agent: SolanaAgentKit,
|
||||
vaultNameOrAddress: string,
|
||||
) {
|
||||
try {
|
||||
const { vaultClient, cleanUp } = await initClients(agent);
|
||||
const vaultPublicKey = getVaultAddressSync(
|
||||
vaultClient.program.programId,
|
||||
encodeName(vaultName),
|
||||
const vaultPublicKey = validateAndEncodeAddress(
|
||||
vaultNameOrAddress,
|
||||
vaultClient.program.programId.toBase58(),
|
||||
);
|
||||
const [vaultDetails, vaultBalance] = await Promise.all([
|
||||
vaultClient.getVault(vaultPublicKey),
|
||||
@@ -302,7 +318,7 @@ export async function getVaultInfo(agent: SolanaAgentKit, vaultName: string) {
|
||||
|
||||
const spotToken = MainnetSpotMarkets[vaultDetails.spotMarketIndex];
|
||||
const data = {
|
||||
name: vaultName,
|
||||
name: decodeName(vaultDetails.name),
|
||||
delegate: vaultDetails.delegate.toBase58(),
|
||||
address: vaultPublicKey.toBase58(),
|
||||
marketName: `${spotToken.symbol}-SPOT`,
|
||||
@@ -346,9 +362,10 @@ export async function depositIntoVault(
|
||||
|
||||
try {
|
||||
const vaultPublicKey = new PublicKey(vault);
|
||||
const [isOwned, vaultDetails] = await Promise.all([
|
||||
const [isOwned, vaultDetails, vaultDepositor] = await Promise.all([
|
||||
getIsOwned(agent, vault),
|
||||
vaultClient.getVault(vaultPublicKey),
|
||||
getOrCreateVaultDepositor(agent, vault),
|
||||
]);
|
||||
const spotMarket = driftClient.getSpotMarketAccount(
|
||||
vaultDetails.spotMarketIndex,
|
||||
@@ -365,7 +382,6 @@ export async function depositIntoVault(
|
||||
return await vaultClient.managerDeposit(vaultPublicKey, amountBN);
|
||||
}
|
||||
|
||||
const vaultDepositor = await getOrCreateVaultDepositor(agent, vault);
|
||||
const tx = await vaultClient.deposit(vaultDepositor, amountBN);
|
||||
|
||||
await cleanUp();
|
||||
@@ -396,7 +412,7 @@ export async function requestWithdrawalFromVault(
|
||||
if (isOwned) {
|
||||
return await vaultClient.managerRequestWithdraw(
|
||||
vaultPublicKey,
|
||||
new BN(amount.toFixed(0)),
|
||||
numberToSafeBN(amount, QUOTE_PRECISION),
|
||||
WithdrawUnit.TOKEN,
|
||||
);
|
||||
}
|
||||
@@ -405,7 +421,7 @@ export async function requestWithdrawalFromVault(
|
||||
|
||||
const tx = await vaultClient.requestWithdraw(
|
||||
vaultDepositor,
|
||||
new BN(amount.toFixed(0)),
|
||||
numberToSafeBN(amount, QUOTE_PRECISION),
|
||||
WithdrawUnit.TOKEN,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user