mirror of
https://github.com/d0zingcat/solana-agent-kit.git
synced 2026-05-19 07:36:46 +00:00
Add Voltr check balance, deposit and withdraw strategy (#128)
# Pull Request Description ## Related Issue Fixes # (issue number) ## Changes Made This PR adds the following changes: <!-- List the key changes made in this PR --> - Query Voltr vault and strategies balances - Withdraw from Voltr strategies - Deposit into Voltr strategies ## Implementation Details <!-- Provide technical details about the implementation --> - utilises Voltr's SDK `@voltr/sdk` to instantiate a `VoltrClient` - find and fetch relevant accounts to create instructions using `VoltrClient` ## Transaction executed by agent <!-- If applicable, provide example usage, transactions, or screenshots --> Example transaction: https://solana.fm/tx/GnUd38TMhtBYNv29nNAyESEWLwjHhUW6hraNrPE3RTF6LtdqNtnoBBqEKptT5JaWqv6TiFp6MeooUa9Rt7vMAu9?cluster=mainnet-alpha Demo: https://x.com/voltrxyz/status/1875204418465059189 ## Prompt Used <!-- If relevant, include the prompt or configuration used --> Tested on autonomous mode. ``` async function runAutonomousMode(agent: any, config: any, interval = 10) { console.log("Starting autonomous mode..."); let iterations = 0; while (true) { try { const evenThought = "1. Get the total amount and amount for each strategy of a Voltr vault: 3ab3KVY9GbDbUUbRnYNSBDQqABTDup7HmdgADHGpB8Bq. " + "2. Take note of the strategies id with the their respective amount. " + "3. Calculate the sum of all strategy amounts. " + "4. Subtract that sum from the vault total to get the excess amount. " + "5. Indicate the excess amount and the strategy id with the lowest amount."; const oddThought = "Using the latest excess amount, if it is 0 then do nothing. " + "Else if it is more than 0, deposit the excess amount into the lowest strategy and vault: 3ab3KVY9GbDbUUbRnYNSBDQqABTDup7HmdgADHGpB8Bq."; const thought = iterations % 2 === 0 ? evenThought : oddThought; const stream = await agent.stream( { messages: [new HumanMessage(thought)] }, config, ); for await (const chunk of stream) { if ("agent" in chunk) { for (const message of chunk.agent.messages) { console.log(message.content); } } else if ("tools" in chunk) { for (const message of chunk.tools.messages) { console.log(message.content); } } console.log("-------------------"); } iterations++; await new Promise((resolve) => setTimeout(resolve, interval * 1000)); } catch (error) { if (error instanceof Error) { console.error("Error:", error.message); } process.exit(1); } } } ``` ## Additional Notes <!-- Any additional information that reviewers should know --> ## Checklist - [x] I have tested these changes locally - [x] I have updated the documentation - [x] I have added a transaction link - [x] I have added the prompt used to test it
This commit is contained in:
32
README.md
32
README.md
@@ -466,6 +466,38 @@ Update the address a drift vault is delegated to.
|
||||
const signature = await agent.updateDriftVaultDelegate("41Y8C4oxk4zgJT1KXyQr35UhZcfsp5mP86Z2G7UUzojU", "new-address")
|
||||
```
|
||||
|
||||
### Get Voltr Vault Position Values
|
||||
|
||||
Get the current position values and total value of assets in a Voltr vault.
|
||||
|
||||
```typescript
|
||||
const values = await agent.voltrGetPositionValues("7opUkqYtxmQRriZvwZkPcg6LqmGjAh1RSEsVrdsGDx5K")
|
||||
```
|
||||
|
||||
### Deposit into Voltr Strategy
|
||||
|
||||
Deposit assets into a specific strategy within a Voltr vault.
|
||||
|
||||
```typescript
|
||||
const signature = await agent.voltrDepositStrategy(
|
||||
new BN("1000000000"), // amount in base units (e.g., 1 USDC = 1000000)
|
||||
"7opUkqYtxmQRriZvwZkPcg6LqmGjAh1RSEsVrdsGDx5K", // vault
|
||||
"9ZQQYvr4x7AMqd6abVa1f5duGjti5wk1MHsX6hogPsLk" // strategy
|
||||
)
|
||||
```
|
||||
|
||||
### Withdraw from Voltr Strategy
|
||||
|
||||
Withdraw assets from a specific strategy within a Voltr vault.
|
||||
|
||||
```typescript
|
||||
const signature = await agent.voltrWithdrawStrategy(
|
||||
new BN("1000000000"), // amount in base units (e.g., 1 USDC = 1000000)
|
||||
"7opUkqYtxmQRriZvwZkPcg6LqmGjAh1RSEsVrdsGDx5K", // vault
|
||||
"9ZQQYvr4x7AMqd6abVa1f5duGjti5wk1MHsX6hogPsLk" // strategy
|
||||
)
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### LangGraph Multi-Agent System
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"@sqds/multisig": "^2.1.3",
|
||||
"@tensor-oss/tensorswap-sdk": "^4.5.0",
|
||||
"@tiplink/api": "^0.3.1",
|
||||
"@voltr/vault-sdk": "^0.1.1",
|
||||
"ai": "^4.0.22",
|
||||
"bn.js": "^5.2.1",
|
||||
"bs58": "^6.0.0",
|
||||
|
||||
28
pnpm-lock.yaml
generated
28
pnpm-lock.yaml
generated
@@ -95,6 +95,9 @@ importers:
|
||||
'@tiplink/api':
|
||||
specifier: ^0.3.1
|
||||
version: 0.3.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(sodium-native@3.4.1)(utf-8-validate@5.0.10)
|
||||
'@voltr/vault-sdk':
|
||||
specifier: ^0.1.1
|
||||
version: 0.1.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.2)(utf-8-validate@5.0.10)
|
||||
ai:
|
||||
specifier: ^4.0.22
|
||||
version: 4.0.22(react@19.0.0)(zod@3.24.1)
|
||||
@@ -1606,6 +1609,9 @@ packages:
|
||||
'@ungap/structured-clone@1.2.1':
|
||||
resolution: {integrity: sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==}
|
||||
|
||||
'@voltr/vault-sdk@0.1.1':
|
||||
resolution: {integrity: sha512-xh8bxPCwNpjVqEN32+Q40Xf08vdORAmQACDE6ru3T+9qrwNgraLcPEzvWeBNTE0FAMAZdNsYOxWbc2FSK0ZQww==}
|
||||
|
||||
'@wallet-standard/base@1.1.0':
|
||||
resolution: {integrity: sha512-DJDQhjKmSNVLKWItoKThJS+CsJQjR9AOBOirBVT1F9YpRyC9oYHE+ZnSf8y8bxUphtKqdQMPVQ2mHohYdRvDVQ==}
|
||||
engines: {node: '>=16'}
|
||||
@@ -5624,7 +5630,7 @@ snapshots:
|
||||
|
||||
'@metaplex-foundation/beet-solana@0.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)':
|
||||
dependencies:
|
||||
'@metaplex-foundation/beet': 0.7.1
|
||||
'@metaplex-foundation/beet': 0.7.2
|
||||
'@solana/web3.js': 1.98.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
|
||||
bs58: 5.0.0
|
||||
debug: 4.4.0
|
||||
@@ -5834,8 +5840,8 @@ snapshots:
|
||||
|
||||
'@metaplex-foundation/mpl-token-metadata@2.13.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(utf-8-validate@5.0.10)':
|
||||
dependencies:
|
||||
'@metaplex-foundation/beet': 0.7.1
|
||||
'@metaplex-foundation/beet-solana': 0.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
|
||||
'@metaplex-foundation/beet': 0.7.2
|
||||
'@metaplex-foundation/beet-solana': 0.4.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)
|
||||
'@metaplex-foundation/cusper': 0.0.2
|
||||
'@solana/spl-token': 0.3.11(@solana/web3.js@1.98.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(utf-8-validate@5.0.10)
|
||||
'@solana/web3.js': 1.98.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
|
||||
@@ -5851,8 +5857,8 @@ snapshots:
|
||||
|
||||
'@metaplex-foundation/mpl-token-metadata@2.13.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.2)(utf-8-validate@5.0.10)':
|
||||
dependencies:
|
||||
'@metaplex-foundation/beet': 0.7.1
|
||||
'@metaplex-foundation/beet-solana': 0.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
|
||||
'@metaplex-foundation/beet': 0.7.2
|
||||
'@metaplex-foundation/beet-solana': 0.4.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)
|
||||
'@metaplex-foundation/cusper': 0.0.2
|
||||
'@solana/spl-token': 0.3.11(@solana/web3.js@1.98.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.2)(utf-8-validate@5.0.10)
|
||||
'@solana/web3.js': 1.98.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
|
||||
@@ -7535,6 +7541,18 @@ snapshots:
|
||||
|
||||
'@ungap/structured-clone@1.2.1': {}
|
||||
|
||||
'@voltr/vault-sdk@0.1.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.2)(utf-8-validate@5.0.10)':
|
||||
dependencies:
|
||||
'@coral-xyz/anchor': 0.30.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)
|
||||
'@solana/spl-token': 0.4.9(@solana/web3.js@1.98.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.2)(utf-8-validate@5.0.10)
|
||||
'@solana/web3.js': 1.98.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- encoding
|
||||
- fastestsmallesttextencoderdecoder
|
||||
- typescript
|
||||
- utf-8-validate
|
||||
|
||||
'@wallet-standard/base@1.1.0': {}
|
||||
|
||||
'@wallet-standard/features@1.1.0':
|
||||
|
||||
@@ -59,6 +59,9 @@ import withdrawFromDriftAccountAction from "./drift/withdrawFromDriftAccount";
|
||||
import driftUserAccountInfoAction from "./drift/driftUserAccountInfo";
|
||||
import deriveDriftVaultAddressAction from "./drift/deriveVaultAddress";
|
||||
import updateDriftVaultDelegateAction from "./drift/updateDriftVaultDelegate";
|
||||
import getVoltrPositionValuesAction from "./voltr/getPositionValues";
|
||||
import depositVoltrStrategyAction from "./voltr/depositStrategy";
|
||||
import withdrawVoltrStrategyAction from "./voltr/withdrawStrategy";
|
||||
|
||||
export const ACTIONS = {
|
||||
WALLET_ADDRESS_ACTION: getWalletAddressAction,
|
||||
@@ -123,6 +126,9 @@ export const ACTIONS = {
|
||||
DRIFT_USER_ACCOUNT_INFO_ACTION: driftUserAccountInfoAction,
|
||||
DERIVE_DRIFT_VAULT_ADDRESS_ACTION: deriveDriftVaultAddressAction,
|
||||
UPDATE_DRIFT_VAULT_DELEGATE_ACTION: updateDriftVaultDelegateAction,
|
||||
GET_VOLTR_POSITION_VALUES_ACTION: getVoltrPositionValuesAction,
|
||||
DEPOSIT_VOLTR_STRATEGY_ACTION: depositVoltrStrategyAction,
|
||||
WITHDRAW_VOLTR_STRATEGY_ACTION: withdrawVoltrStrategyAction,
|
||||
};
|
||||
|
||||
export type { Action, ActionExample, Handler } from "../types/action";
|
||||
|
||||
83
src/actions/voltr/depositStrategy.ts
Normal file
83
src/actions/voltr/depositStrategy.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { Action } from "../../types/action";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import { z } from "zod";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { BN } from "bn.js";
|
||||
|
||||
const depositVoltrStrategyAction: Action = {
|
||||
name: "DEPOSIT_VOLTR_STRATEGY",
|
||||
similes: [
|
||||
"deposit to voltr strategy",
|
||||
"add funds to voltr vault strategy",
|
||||
"invest in voltr strategy",
|
||||
"deposit assets to voltr",
|
||||
"contribute to voltr vault",
|
||||
"fund voltr strategy",
|
||||
],
|
||||
description: "Deposit assets into a specific strategy within a Voltr vault",
|
||||
examples: [
|
||||
[
|
||||
{
|
||||
input: {
|
||||
depositAmount: "1000000000", // 1 USDC with 6 decimals
|
||||
vault: "7opUkqYtxmQRriZvwZkPcg6LqmGjAh1RSEsVrdsGDx5K",
|
||||
strategy: "9ZQQYvr4x7AMqd6abVa1f5duGjti5wk1MHsX6hogPsLk",
|
||||
},
|
||||
output: {
|
||||
status: "success",
|
||||
vault: "7opUkqYtxmQRriZvwZkPcg6LqmGjAh1RSEsVrdsGDx5K",
|
||||
strategy: "9ZQQYvr4x7AMqd6abVa1f5duGjti5wk1MHsX6hogPsLk",
|
||||
signature: "2ZE7Rz...",
|
||||
message: "Successfully deposited 1000000000 into strategy",
|
||||
},
|
||||
explanation: "Deposit 1 USDC into a Voltr vault strategy",
|
||||
},
|
||||
],
|
||||
],
|
||||
schema: z.object({
|
||||
depositAmount: z
|
||||
.string()
|
||||
.min(1)
|
||||
.describe("The amount to deposit (in base units including decimals)"),
|
||||
vault: z
|
||||
.string()
|
||||
.min(1)
|
||||
.describe(
|
||||
"The public key of the Voltr source vault to take assets from, e.g., 'Ga27...'",
|
||||
),
|
||||
strategy: z
|
||||
.string()
|
||||
.min(1)
|
||||
.describe(
|
||||
"The public key of the initialized target strategy to deposit into, e.g., 'Jheh...'",
|
||||
),
|
||||
}),
|
||||
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
|
||||
try {
|
||||
const depositAmount = new BN(input.depositAmount);
|
||||
const vault = new PublicKey(input.vault);
|
||||
const strategy = new PublicKey(input.strategy);
|
||||
|
||||
const signature = await agent.voltrDepositStrategy(
|
||||
depositAmount,
|
||||
vault,
|
||||
strategy,
|
||||
);
|
||||
|
||||
return {
|
||||
status: "success",
|
||||
vault: vault.toBase58(),
|
||||
strategy: strategy.toBase58(),
|
||||
signature,
|
||||
message: `Successfully deposited ${input.depositAmount} into strategy`,
|
||||
};
|
||||
} catch (error: any) {
|
||||
return {
|
||||
status: "error",
|
||||
message: `Failed to deposit into strategy: ${error.message}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default depositVoltrStrategyAction;
|
||||
74
src/actions/voltr/getPositionValues.ts
Normal file
74
src/actions/voltr/getPositionValues.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { Action } from "../../types/action";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import { z } from "zod";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
|
||||
const getVoltrPositionValuesAction: Action = {
|
||||
name: "GET_VOLTR_POSITION_VALUES",
|
||||
similes: [
|
||||
"get voltr vault value",
|
||||
"check voltr position",
|
||||
"get voltr vault assets",
|
||||
"view voltr holdings",
|
||||
"check voltr portfolio",
|
||||
"get voltr vault breakdown",
|
||||
],
|
||||
description:
|
||||
"Get the current position values and total assets for a Voltr vault",
|
||||
examples: [
|
||||
[
|
||||
{
|
||||
input: {
|
||||
vault: "7opUkqYtxmQRriZvwZkPcg6LqmGjAh1RSEsVrdsGDx5K",
|
||||
},
|
||||
output: {
|
||||
status: "success",
|
||||
data: {
|
||||
totalValue: 1000000,
|
||||
positions: [
|
||||
{
|
||||
strategy: "4JHtgXyMb9gFJ1hGd2sh645jrZcxurSG3QP7Le3aTMTx",
|
||||
value: 600000,
|
||||
},
|
||||
{
|
||||
strategy: "4i9kzGr1UkxBCCUkQUQ4vsF51fjdt2knKxrwM1h1NW4g",
|
||||
value: 400000,
|
||||
},
|
||||
],
|
||||
},
|
||||
message: "Successfully retrieved Voltr vault position values",
|
||||
},
|
||||
explanation:
|
||||
"Get position values for a Voltr vault showing total value and value per strategy",
|
||||
},
|
||||
],
|
||||
],
|
||||
schema: z.object({
|
||||
vault: z
|
||||
.string()
|
||||
.min(1)
|
||||
.describe("The public key of the Voltr vault to query, e.g., 'Ga27...'"),
|
||||
}),
|
||||
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
|
||||
try {
|
||||
const vault = new PublicKey(input.vault);
|
||||
|
||||
const result = await agent.voltrGetPositionValues(vault);
|
||||
const positionData = JSON.parse(result);
|
||||
|
||||
return {
|
||||
status: "success",
|
||||
vault: vault.toBase58(),
|
||||
data: positionData,
|
||||
message: "Successfully retrieved Voltr vault position values",
|
||||
};
|
||||
} catch (error: any) {
|
||||
return {
|
||||
status: "error",
|
||||
message: `Failed to get vault position values: ${error.message}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default getVoltrPositionValuesAction;
|
||||
83
src/actions/voltr/withdrawStrategy.ts
Normal file
83
src/actions/voltr/withdrawStrategy.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { Action } from "../../types/action";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import { z } from "zod";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { BN } from "bn.js";
|
||||
|
||||
const withdrawVoltrStrategyAction: Action = {
|
||||
name: "WITHDRAW_VOLTR_STRATEGY",
|
||||
similes: [
|
||||
"withdraw from voltr strategy",
|
||||
"remove funds from voltr vault strategy",
|
||||
"take out from voltr strategy",
|
||||
"withdraw assets from voltr",
|
||||
"pull from voltr vault",
|
||||
"redeem from voltr strategy",
|
||||
],
|
||||
description: "Withdraw assets from a specific strategy within a Voltr vault",
|
||||
examples: [
|
||||
[
|
||||
{
|
||||
input: {
|
||||
withdrawAmount: "1000000000", // 1 USDC with 6 decimals
|
||||
vault: "7opUkqYtxmQRriZvwZkPcg6LqmGjAh1RSEsVrdsGDx5K",
|
||||
strategy: "9ZQQYvr4x7AMqd6abVa1f5duGjti5wk1MHsX6hogPsLk",
|
||||
},
|
||||
output: {
|
||||
status: "success",
|
||||
vault: "7opUkqYtxmQRriZvwZkPcg6LqmGjAh1RSEsVrdsGDx5K",
|
||||
strategy: "9ZQQYvr4x7AMqd6abVa1f5duGjti5wk1MHsX6hogPsLk",
|
||||
signature: "2ZE7Rz...",
|
||||
message: "Successfully withdrew 1000000000 from strategy",
|
||||
},
|
||||
explanation: "Withdraw 1 USDC from a Voltr vault strategy",
|
||||
},
|
||||
],
|
||||
],
|
||||
schema: z.object({
|
||||
withdrawAmount: z
|
||||
.string()
|
||||
.min(1)
|
||||
.describe("The amount to withdraw (in base units including decimals)"),
|
||||
vault: z
|
||||
.string()
|
||||
.min(1)
|
||||
.describe(
|
||||
"The public key of the Voltr source vault to deposit assets into, e.g., 'Ga27...'",
|
||||
),
|
||||
strategy: z
|
||||
.string()
|
||||
.min(1)
|
||||
.describe(
|
||||
"The public key of the initialized target strategy to withdraw from, e.g., 'Jheh...'",
|
||||
),
|
||||
}),
|
||||
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
|
||||
try {
|
||||
const withdrawAmount = new BN(input.withdrawAmount);
|
||||
const vault = new PublicKey(input.vault);
|
||||
const strategy = new PublicKey(input.strategy);
|
||||
|
||||
const signature = await agent.voltrWithdrawStrategy(
|
||||
withdrawAmount,
|
||||
vault,
|
||||
strategy,
|
||||
);
|
||||
|
||||
return {
|
||||
status: "success",
|
||||
vault: vault.toBase58(),
|
||||
strategy: strategy.toBase58(),
|
||||
signature,
|
||||
message: `Successfully withdrew ${input.withdrawAmount} from strategy`,
|
||||
};
|
||||
} catch (error: any) {
|
||||
return {
|
||||
status: "error",
|
||||
message: `Failed to withdraw from strategy: ${error.message}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default withdrawVoltrStrategyAction;
|
||||
@@ -98,6 +98,9 @@ import {
|
||||
withdrawFromDriftVault,
|
||||
updateVaultDelegate,
|
||||
get_token_balance,
|
||||
voltrGetPositionValues,
|
||||
voltrDepositStrategy,
|
||||
voltrWithdrawStrategy,
|
||||
} from "../tools";
|
||||
import {
|
||||
Config,
|
||||
@@ -840,4 +843,24 @@ export class SolanaAgentKit {
|
||||
async updateDriftVaultDelegate(vaultAddress: string, delegate: string) {
|
||||
return await updateVaultDelegate(this, vaultAddress, delegate);
|
||||
}
|
||||
|
||||
async voltrDepositStrategy(
|
||||
depositAmount: BN,
|
||||
vault: PublicKey,
|
||||
strategy: PublicKey,
|
||||
): Promise<string> {
|
||||
return voltrDepositStrategy(this, depositAmount, vault, strategy);
|
||||
}
|
||||
|
||||
async voltrWithdrawStrategy(
|
||||
withdrawAmount: BN,
|
||||
vault: PublicKey,
|
||||
strategy: PublicKey,
|
||||
): Promise<string> {
|
||||
return voltrWithdrawStrategy(this, withdrawAmount, vault, strategy);
|
||||
}
|
||||
|
||||
async voltrGetPositionValues(vault: PublicKey): Promise<string> {
|
||||
return voltrGetPositionValues(this, vault);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ export * from "./lightprotocol";
|
||||
export * from "./squads";
|
||||
export * from "./helius";
|
||||
export * from "./drift";
|
||||
export * from "./voltr";
|
||||
|
||||
import { SolanaAgentKit } from "../agent";
|
||||
import {
|
||||
@@ -114,6 +115,9 @@ import {
|
||||
SolanaUpdateDriftVaultTool,
|
||||
SolanaWithdrawFromDriftAccountTool,
|
||||
SolanaWithdrawFromDriftVaultTool,
|
||||
SolanaVoltrGetPositionValues,
|
||||
SolanaVoltrDepositStrategy,
|
||||
SolanaVoltrWithdrawStrategy,
|
||||
} from "./index";
|
||||
|
||||
export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
||||
@@ -208,5 +212,8 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
||||
new SolanaDriftVaultInfoTool(solanaKit),
|
||||
new SolanaWithdrawFromDriftAccountTool(solanaKit),
|
||||
new SolanaWithdrawFromDriftVaultTool(solanaKit),
|
||||
new SolanaVoltrGetPositionValues(solanaKit),
|
||||
new SolanaVoltrDepositStrategy(solanaKit),
|
||||
new SolanaVoltrWithdrawStrategy(solanaKit),
|
||||
];
|
||||
}
|
||||
|
||||
39
src/langchain/voltr/deposit_strategy.ts
Normal file
39
src/langchain/voltr/deposit_strategy.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Tool } from "langchain/tools";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { BN } from "bn.js";
|
||||
|
||||
export class SolanaVoltrDepositStrategy extends Tool {
|
||||
name = "solana_voltr_deposit_strategy";
|
||||
description = `Deposit amount into a strategy for Voltr's vaults
|
||||
|
||||
Inputs (input is a json string):
|
||||
depositAmount: number (required)
|
||||
vault: string (required)
|
||||
strategy: string (required)
|
||||
`;
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const inputFormat = JSON.parse(input);
|
||||
const tx = await this.solanaKit.voltrDepositStrategy(
|
||||
new BN(inputFormat.depositAmount),
|
||||
new PublicKey(inputFormat.vault),
|
||||
new PublicKey(inputFormat.strategy),
|
||||
);
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
message: `Deposited ${inputFormat.depositAmount} into strategy ${inputFormat.strategy} of vault ${inputFormat.vault} successfully`,
|
||||
transaction: tx,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "UNKNOWN_ERROR",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/langchain/voltr/get_position_values.ts
Normal file
18
src/langchain/voltr/get_position_values.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Tool } from "langchain/tools";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
|
||||
export class SolanaVoltrGetPositionValues extends Tool {
|
||||
name = "solana_voltr_get_position_values";
|
||||
description = `Get the total asset value and current value for each strategy of a given Voltr vault
|
||||
|
||||
Inputs:
|
||||
vault: string (required)
|
||||
`;
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
async _call(input: string): Promise<string> {
|
||||
return this.solanaKit.voltrGetPositionValues(new PublicKey(input));
|
||||
}
|
||||
}
|
||||
3
src/langchain/voltr/index.ts
Normal file
3
src/langchain/voltr/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./deposit_strategy";
|
||||
export * from "./withdraw_strategy";
|
||||
export * from "./get_position_values";
|
||||
39
src/langchain/voltr/withdraw_strategy.ts
Normal file
39
src/langchain/voltr/withdraw_strategy.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Tool } from "langchain/tools";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { BN } from "bn.js";
|
||||
|
||||
export class SolanaVoltrWithdrawStrategy extends Tool {
|
||||
name = "solana_voltr_withdraw_strategy";
|
||||
description = `Withdraw amount from a strategy for Voltr's vaults
|
||||
|
||||
Inputs (input is a json string):
|
||||
withdrawAmount: number (required)
|
||||
vault: string (required)
|
||||
strategy: string (required)
|
||||
`;
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const inputFormat = JSON.parse(input);
|
||||
const tx = await this.solanaKit.voltrWithdrawStrategy(
|
||||
new BN(inputFormat.withdrawAmount),
|
||||
new PublicKey(inputFormat.vault),
|
||||
new PublicKey(inputFormat.strategy),
|
||||
);
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
message: `Withdrew ${inputFormat.withdrawAmount} from strategy ${inputFormat.strategy} of vault ${inputFormat.vault} successfully`,
|
||||
transaction: tx,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "UNKNOWN_ERROR",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,3 +25,4 @@ export * from "./tiplink";
|
||||
export * from "./lightprotocol";
|
||||
export * from "./squads";
|
||||
export * from "./helius";
|
||||
export * from "./voltr";
|
||||
|
||||
3
src/tools/voltr/index.ts
Normal file
3
src/tools/voltr/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./voltr_deposit_strategy";
|
||||
export * from "./voltr_withdraw_strategy";
|
||||
export * from "./voltr_get_position_values";
|
||||
99
src/tools/voltr/voltr_deposit_strategy.ts
Normal file
99
src/tools/voltr/voltr_deposit_strategy.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import {
|
||||
PublicKey,
|
||||
sendAndConfirmTransaction,
|
||||
Transaction,
|
||||
} from "@solana/web3.js";
|
||||
import { VoltrClient } from "@voltr/vault-sdk";
|
||||
import BN from "bn.js";
|
||||
|
||||
/**
|
||||
* Deposits assets into a Voltr strategy
|
||||
* @param agent SolanaAgentKit instance
|
||||
* @param depositAmount Amount to deposit in base units (BN)
|
||||
* @param vault Public key of the target vault
|
||||
* @param strategy Public key of the target strategy
|
||||
* @returns Transaction signature for the deposit
|
||||
*/
|
||||
export async function voltrDepositStrategy(
|
||||
agent: SolanaAgentKit,
|
||||
depositAmount: BN,
|
||||
vault: PublicKey,
|
||||
strategy: PublicKey,
|
||||
): Promise<string> {
|
||||
const vc = new VoltrClient(agent.connection, agent.wallet);
|
||||
const vaultAccount = await vc.fetchVaultAccount(vault);
|
||||
const vaultAssetMint = vaultAccount.asset.mint;
|
||||
const assetTokenProgram = await agent.connection
|
||||
.getAccountInfo(new PublicKey(vaultAssetMint))
|
||||
.then((account) => account?.owner);
|
||||
|
||||
if (
|
||||
!assetTokenProgram ||
|
||||
!(
|
||||
assetTokenProgram.equals(TOKEN_PROGRAM_ID) ||
|
||||
assetTokenProgram.equals(TOKEN_2022_PROGRAM_ID)
|
||||
)
|
||||
) {
|
||||
throw new Error("Invalid asset token program");
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
`https://voltr.xyz/api/remaining-accounts/deposit-strategy?vault=${vault.toBase58()}&strategy=${strategy.toBase58()}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const data = (await response.json()).data as {
|
||||
instructionDiscriminator: number[] | null;
|
||||
additionalArgs: number[] | null;
|
||||
remainingAccounts:
|
||||
| {
|
||||
pubkey: string;
|
||||
isSigner: boolean;
|
||||
isWritable: boolean;
|
||||
}[]
|
||||
| null;
|
||||
};
|
||||
|
||||
const additionalArgs = data.additionalArgs
|
||||
? Buffer.from(data.additionalArgs)
|
||||
: null;
|
||||
const instructionDiscriminator = data.instructionDiscriminator
|
||||
? Buffer.from(data.instructionDiscriminator)
|
||||
: null;
|
||||
const remainingAccounts =
|
||||
data.remainingAccounts?.map((account) => ({
|
||||
pubkey: new PublicKey(account.pubkey),
|
||||
isSigner: account.isSigner,
|
||||
isWritable: account.isWritable,
|
||||
})) ?? [];
|
||||
|
||||
const depositIx = await vc.createDepositStrategyIx(
|
||||
{
|
||||
depositAmount,
|
||||
additionalArgs,
|
||||
instructionDiscriminator,
|
||||
},
|
||||
{
|
||||
vault,
|
||||
vaultAssetMint,
|
||||
strategy: strategy,
|
||||
assetTokenProgram,
|
||||
remainingAccounts,
|
||||
},
|
||||
);
|
||||
|
||||
const transaction = new Transaction();
|
||||
transaction.add(depositIx);
|
||||
|
||||
const txSig = await sendAndConfirmTransaction(agent.connection, transaction, [
|
||||
agent.wallet,
|
||||
]);
|
||||
return txSig;
|
||||
}
|
||||
20
src/tools/voltr/voltr_get_position_values.ts
Normal file
20
src/tools/voltr/voltr_get_position_values.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { VoltrClient } from "@voltr/vault-sdk";
|
||||
|
||||
/**
|
||||
* Gets the value of assets in a Voltr vault
|
||||
* @param agent SolanaAgentKit instance
|
||||
* @param vault Public key of the target vault
|
||||
* @returns Position and total values for the vault
|
||||
*/
|
||||
export async function voltrGetPositionValues(
|
||||
agent: SolanaAgentKit,
|
||||
vault: PublicKey,
|
||||
): Promise<string> {
|
||||
const vc = new VoltrClient(agent.connection, agent.wallet);
|
||||
const positionAndTotalValues =
|
||||
await vc.getPositionAndTotalValuesForVault(vault);
|
||||
|
||||
return JSON.stringify(positionAndTotalValues);
|
||||
}
|
||||
99
src/tools/voltr/voltr_withdraw_strategy.ts
Normal file
99
src/tools/voltr/voltr_withdraw_strategy.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import {
|
||||
PublicKey,
|
||||
sendAndConfirmTransaction,
|
||||
Transaction,
|
||||
} from "@solana/web3.js";
|
||||
import BN from "bn.js";
|
||||
import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
|
||||
import { VoltrClient } from "@voltr/vault-sdk";
|
||||
|
||||
/**
|
||||
* Withdraws assets from a Voltr strategy
|
||||
* @param agent SolanaAgentKit instance
|
||||
* @param withdrawAmount Amount to withdraw in base units (BN)
|
||||
* @param vault Public key of the target vault
|
||||
* @param strategy Public key of the target strategy
|
||||
* @returns Transaction signature for the deposit
|
||||
*/
|
||||
export async function voltrWithdrawStrategy(
|
||||
agent: SolanaAgentKit,
|
||||
withdrawAmount: BN,
|
||||
vault: PublicKey,
|
||||
strategy: PublicKey,
|
||||
): Promise<string> {
|
||||
const vc = new VoltrClient(agent.connection, agent.wallet);
|
||||
const vaultAccount = await vc.fetchVaultAccount(vault);
|
||||
const vaultAssetMint = vaultAccount.asset.mint;
|
||||
const assetTokenProgram = await agent.connection
|
||||
.getAccountInfo(new PublicKey(vaultAssetMint))
|
||||
.then((account) => account?.owner);
|
||||
|
||||
if (
|
||||
!assetTokenProgram ||
|
||||
!(
|
||||
assetTokenProgram.equals(TOKEN_PROGRAM_ID) ||
|
||||
assetTokenProgram.equals(TOKEN_2022_PROGRAM_ID)
|
||||
)
|
||||
) {
|
||||
throw new Error("Invalid asset token program");
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
`https://voltr.xyz/api/remaining-accounts/deposit-strategy?vault=${vault.toBase58()}&strategy=${strategy.toBase58()}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const data = (await response.json()).data as {
|
||||
instructionDiscriminator: number[] | null;
|
||||
additionalArgs: number[] | null;
|
||||
remainingAccounts:
|
||||
| {
|
||||
pubkey: string;
|
||||
isSigner: boolean;
|
||||
isWritable: boolean;
|
||||
}[]
|
||||
| null;
|
||||
};
|
||||
|
||||
const additionalArgs = data.additionalArgs
|
||||
? Buffer.from(data.additionalArgs)
|
||||
: null;
|
||||
const instructionDiscriminator = data.instructionDiscriminator
|
||||
? Buffer.from(data.instructionDiscriminator)
|
||||
: null;
|
||||
const remainingAccounts =
|
||||
data.remainingAccounts?.map((account) => ({
|
||||
pubkey: new PublicKey(account.pubkey),
|
||||
isSigner: account.isSigner,
|
||||
isWritable: account.isWritable,
|
||||
})) ?? [];
|
||||
|
||||
const withdrawIx = await vc.createWithdrawStrategyIx(
|
||||
{
|
||||
withdrawAmount,
|
||||
additionalArgs,
|
||||
instructionDiscriminator,
|
||||
},
|
||||
{
|
||||
vault,
|
||||
vaultAssetMint,
|
||||
strategy,
|
||||
assetTokenProgram,
|
||||
remainingAccounts,
|
||||
},
|
||||
);
|
||||
|
||||
const transaction = new Transaction();
|
||||
transaction.add(withdrawIx);
|
||||
|
||||
const txSig = await sendAndConfirmTransaction(agent.connection, transaction, [
|
||||
agent.wallet,
|
||||
]);
|
||||
return txSig;
|
||||
}
|
||||
Reference in New Issue
Block a user