diff --git a/README.md b/README.md index 7b73eb4..6a1a2c8 100644 --- a/README.md +++ b/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. \ No newline at end of file +This toolkit handles private keys and transactions. Always ensure you're using it in a secure environment and never share your private keys. diff --git a/src/actions/drift/vaultInfo.ts b/src/actions/drift/vaultInfo.ts index 279f78b..3343f2f 100644 --- a/src/actions/drift/vaultInfo.ts +++ b/src/actions/drift/vaultInfo.ts @@ -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", diff --git a/src/tools/drift/drift_vault.ts b/src/tools/drift/drift_vault.ts index a65c485..541c117 100644 --- a/src/tools/drift/drift_vault.ts +++ b/src/tools/drift/drift_vault.ts @@ -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, );