fix: changes for Voltr vault program upgrade

This commit is contained in:
jakeyvee
2025-01-15 18:15:35 +08:00
parent b56116df09
commit c71f2159fd
9 changed files with 141 additions and 130 deletions

View File

@@ -48,7 +48,7 @@
"@tensor-oss/tensorswap-sdk": "^4.5.0",
"@solana/web3.js": "^1.98.0",
"@tiplink/api": "^0.3.1",
"@voltr/sdk": "^0.1.0",
"@voltr/vault-sdk": "^0.1.1",
"bn.js": "^5.2.1",
"bs58": "^6.0.0",
"chai": "^5.1.2",

10
pnpm-lock.yaml generated
View File

@@ -80,9 +80,9 @@ dependencies:
'@tiplink/api':
specifier: ^0.3.1
version: 0.3.1(fastestsmallesttextencoderdecoder@1.0.22)(sodium-native@3.4.1)
'@voltr/sdk':
specifier: ^0.1.0
version: 0.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.2)
'@voltr/vault-sdk':
specifier: ^0.1.1
version: 0.1.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.2)
ai:
specifier: ^4.0.22
version: 4.0.25(react@19.0.0)(zod@3.24.1)
@@ -2303,8 +2303,8 @@ packages:
/@ungap/structured-clone@1.2.1:
resolution: {integrity: sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==}
/@voltr/sdk@0.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.2):
resolution: {integrity: sha512-iLb0zc3ClZYJ9DBgMeuONSnZKa8r54MGj2LfN+4ZXXDx/O+ssjuuFPE+tcmWU0tL0yfHOLRgwWEPc4yynWG3Rg==}
/@voltr/vault-sdk@0.1.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.2):
resolution: {integrity: sha512-xh8bxPCwNpjVqEN32+Q40Xf08vdORAmQACDE6ru3T+9qrwNgraLcPEzvWeBNTE0FAMAZdNsYOxWbc2FSK0ZQww==}
dependencies:
'@coral-xyz/anchor': 0.30.1
'@solana/spl-token': 0.4.9(@solana/web3.js@1.98.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.2)

View File

@@ -55,7 +55,7 @@ import {
fetchTokenReportSummary,
fetchTokenDetailedReport,
OrderParams,
voltrGetAssetAmount,
voltrGetPositionValues,
voltrDepositStrategy,
voltrWithdrawStrategy,
} from "../tools";
@@ -517,7 +517,7 @@ export class SolanaAgentKit {
return voltrWithdrawStrategy(this, withdrawAmount, vault, strategy);
}
async voltrGetAssetAmount(vault: PublicKey): Promise<string> {
return voltrGetAssetAmount(this, vault);
async voltrGetPositionValues(vault: PublicKey): Promise<string> {
return voltrGetPositionValues(this, vault);
}
}

View File

@@ -2083,9 +2083,9 @@ export class SolanaVoltrWithdrawStrategy extends Tool {
}
}
export class SolanaVoltrGetAssetAmount extends Tool {
name = "solana_voltr_get_asset_amount";
description = `Get the total asset amount and current amount for each strategy of a given Voltr vault
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)
@@ -2094,7 +2094,7 @@ export class SolanaVoltrGetAssetAmount extends Tool {
super();
}
async _call(input: string): Promise<string> {
return this.solanaKit.voltrGetAssetAmount(new PublicKey(input));
return this.solanaKit.voltrGetPositionValues(new PublicKey(input));
}
}
@@ -2152,6 +2152,6 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
new SolanaFetchTokenDetailedReportTool(solanaKit),
new SolanaVoltrDepositStrategy(solanaKit),
new SolanaVoltrWithdrawStrategy(solanaKit),
new SolanaVoltrGetAssetAmount(solanaKit),
new SolanaVoltrGetPositionValues(solanaKit),
];
}

View File

@@ -61,4 +61,4 @@ export * from "./rugcheck";
export * from "./voltr_deposit_strategy";
export * from "./voltr_withdraw_strategy";
export * from "./voltr_get_asset_amount";
export * from "./voltr_get_position_values";

View File

@@ -1,10 +1,11 @@
import { VoltrClient } from "@voltr/sdk";
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";
/**
@@ -22,13 +23,21 @@ export async function voltrDepositStrategy(
strategy: PublicKey,
): Promise<string> {
const vc = new VoltrClient(agent.connection, agent.wallet);
const { vaultAssetIdleAuth } = vc.findVaultAddresses(vault);
const vaultAccount = await vc.fetchVaultAccount(vault);
const vaultAssetMint = vaultAccount.asset.assetMint;
const strategyAccount = await vc.fetchStrategyAccount(strategy);
const liquidityReserve = strategyAccount.counterpartyAssetTa;
const protocolProgram = strategyAccount.protocolProgram;
const vaultStrategy = vc.findVaultStrategy(vaultAssetIdleAuth, strategy);
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()}`,
@@ -41,37 +50,50 @@ export async function voltrDepositStrategy(
);
const data = (await response.json()).data as {
pubkey: string;
isSigner: boolean;
isWritable: boolean;
}[];
instructionDiscriminator: number[] | null;
additionalArgs: number[] | null;
remainingAccounts:
| {
pubkey: string;
isSigner: boolean;
isWritable: boolean;
}[]
| null;
};
const remainingAccounts = data.map((account) => ({
pubkey: new PublicKey(account.pubkey),
isSigner: account.isSigner,
isWritable: account.isWritable,
}));
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, {
vault,
vaultAssetMint,
strategy: strategy,
vaultStrategy: vaultStrategy,
counterpartyAssetTa: liquidityReserve,
protocolProgram: protocolProgram,
remainingAccounts,
});
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],
{
commitment: "confirmed",
},
);
const txSig = await sendAndConfirmTransaction(agent.connection, transaction, [
agent.wallet,
]);
return txSig;
}

View File

@@ -1,33 +0,0 @@
import { VoltrClient } from "@voltr/sdk";
import { SolanaAgentKit } from "../agent";
import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";
/**
* Deposits assets into a Voltr strategy
* @param agent SolanaAgentKit instance
* @param vault Public key of the target vault
* @returns Transaction signature for the deposit
*/
export async function voltrGetAssetAmount(
agent: SolanaAgentKit,
vault: PublicKey,
): Promise<string> {
const vc = new VoltrClient(agent.connection, agent.wallet);
const vaultAccount = await vc.fetchVaultAccount(vault);
const totalAssetAmount: BN = vaultAccount.asset.totalAmount;
const { vaultAssetIdleAuth } = vc.findVaultAddresses(vault);
const vaultStrategyAccounts =
await vc.fetchVaultStrategyAccounts(vaultAssetIdleAuth);
const strategyInfo = vaultStrategyAccounts.map((vaultStrategyAccount) => ({
strategyId: vaultStrategyAccount.account.strategy.toBase58(),
amount: vaultStrategyAccount.account.currentAmount.toString(),
}));
const result = {
totalAmount: totalAssetAmount.toString(),
strategies: strategyInfo,
};
return JSON.stringify(result);
}

View 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);
}

View File

@@ -1,4 +1,3 @@
import { VoltrClient } from "@voltr/sdk";
import { SolanaAgentKit } from "../agent";
import {
PublicKey,
@@ -6,12 +5,8 @@ import {
Transaction,
} from "@solana/web3.js";
import BN from "bn.js";
import {
Account,
getAccount,
TOKEN_2022_PROGRAM_ID,
TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { VoltrClient } from "@voltr/vault-sdk";
/**
* Withdraws assets from a Voltr strategy
@@ -28,34 +23,24 @@ export async function voltrWithdrawStrategy(
strategy: PublicKey,
): Promise<string> {
const vc = new VoltrClient(agent.connection, agent.wallet);
const { vaultAssetIdleAuth } = vc.findVaultAddresses(vault);
const vaultAccount = await vc.fetchVaultAccount(vault);
const vaultAssetMint = vaultAccount.asset.assetMint;
const strategyAccount = await vc.fetchStrategyAccount(strategy);
const liquidityReserve = strategyAccount.counterpartyAssetTa;
const protocolProgram = strategyAccount.protocolProgram;
const vaultStrategy = vc.findVaultStrategy(vaultAssetIdleAuth, strategy);
const vaultAssetMint = vaultAccount.asset.mint;
const assetTokenProgram = await agent.connection
.getAccountInfo(new PublicKey(vaultAssetMint))
.then((account) => account?.owner);
let liquidityReserveAccount: Account;
try {
liquidityReserveAccount = await getAccount(
agent.connection,
liquidityReserve,
"confirmed",
TOKEN_PROGRAM_ID,
);
} catch (error) {
liquidityReserveAccount = await getAccount(
agent.connection,
liquidityReserve,
"confirmed",
TOKEN_2022_PROGRAM_ID,
);
if (
!assetTokenProgram ||
!(
assetTokenProgram.equals(TOKEN_PROGRAM_ID) ||
assetTokenProgram.equals(TOKEN_2022_PROGRAM_ID)
)
) {
throw new Error("Invalid asset token program");
}
const liquidityReserveAuth = liquidityReserveAccount.owner;
const response = await fetch(
`https://voltr.xyz/api/remaining-accounts/withdraw-strategy?vault=${vault.toBase58()}&strategy=${strategy.toBase58()}`,
`https://voltr.xyz/api/remaining-accounts/deposit-strategy?vault=${vault.toBase58()}&strategy=${strategy.toBase58()}`,
{
method: "GET",
headers: {
@@ -65,27 +50,44 @@ export async function voltrWithdrawStrategy(
);
const data = (await response.json()).data as {
pubkey: string;
isSigner: boolean;
isWritable: boolean;
}[];
instructionDiscriminator: number[] | null;
additionalArgs: number[] | null;
remainingAccounts:
| {
pubkey: string;
isSigner: boolean;
isWritable: boolean;
}[]
| null;
};
const remainingAccounts = data.map((account) => ({
pubkey: new PublicKey(account.pubkey),
isSigner: account.isSigner,
isWritable: account.isWritable,
}));
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, {
vault,
vaultAssetMint,
strategy: strategy,
vaultStrategy: vaultStrategy,
counterpartyAssetTa: liquidityReserve,
counterpartyAssetTaAuth: liquidityReserveAuth,
protocolProgram: protocolProgram,
remainingAccounts,
});
const withdrawIx = await vc.createWithdrawStrategyIx(
{
withdrawAmount,
additionalArgs,
instructionDiscriminator,
},
{
vault,
vaultAssetMint,
strategy,
assetTokenProgram,
remainingAccounts,
},
);
const transaction = new Transaction();
transaction.add(withdrawIx);