merge: main

This commit is contained in:
michaelessiet
2025-01-15 13:28:58 +01:00
375 changed files with 30301 additions and 3609 deletions

View File

@@ -55,15 +55,3 @@ export async function createSingle(
throw new Error(`Single edition creation failed: ${error.message}`);
}
}
/**
* Buy a single edition on 3Land
* @param
* @returns
*/
// export async function buySingle() {
// try {
// } catch (error: any) {
// throw new Error(`Buying single edition failed: ${error.message}`);
// }
// }

1
src/tools/3land/index.ts Normal file
View File

@@ -0,0 +1 @@
export * from "./create_3land_collectible";

View File

@@ -3,13 +3,13 @@ import {
SystemProgram,
TransactionInstruction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { TOKENS, DEFAULT_OPTIONS } from "../constants";
import { SolanaAgentKit } from "../../index";
import { TOKENS, DEFAULT_OPTIONS } from "../../constants";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { BN } from "@coral-xyz/anchor";
import AdrenaClient from "../utils/AdrenaClient";
import { sendTx } from "../utils/send_tx";
import AdrenaClient from "../../utils/AdrenaClient";
import { sendTx } from "../../utils/send_tx";
const PRICE_DECIMALS = 10;
const ADRENA_PROGRAM_ID = new PublicKey(

View File

@@ -0,0 +1 @@
export * from "./adrena_perp_trading";

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import OpenAI from "openai";
/**

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../agent";
import { SolanaAgentKit } from "../../agent";
/**
* Get the agents wallet address

2
src/tools/agent/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export * from "./create_image";
export * from "./get_wallet_address";

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import { getAllTld } from "@onsol/tldparser";
/**

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../agent";
import { SolanaAgentKit } from "../../agent";
import { PublicKey } from "@solana/web3.js";
import { TldParser } from "@onsol/tldparser";

View File

@@ -1,5 +1,5 @@
import { TldParser } from "@onsol/tldparser";
import { SolanaAgentKit } from "../agent";
import { SolanaAgentKit } from "../../agent";
/**
* Get all domains owned by an address for a specific TLD
* @param agent SolanaAgentKit instance

View File

@@ -0,0 +1,4 @@
export * from "./get_all_domains_tlds";
export * from "./get_owned_all_domains";
export * from "./get_owned_domains_for_tld";
export * from "./resolve_domain";

View File

@@ -1,5 +1,5 @@
import { TldParser } from "@onsol/tldparser";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../agent";
import { PublicKey } from "@solana/web3.js";
/**

View File

@@ -1,5 +1,5 @@
import { PublicKey } from "@solana/web3.js";
import { JupiterTokenData } from "../types";
import { JupiterTokenData } from "../../types";
export async function getTokenDataByAddress(
mint: PublicKey,

View File

@@ -0,0 +1 @@
export * from "./get_token_data";

460
src/tools/drift/drift.ts Normal file
View File

@@ -0,0 +1,460 @@
import {
BASE_PRECISION,
convertToNumber,
DRIFT_PROGRAM_ID,
DriftClient,
FastSingleTxSender,
getLimitOrderParams,
getMarketOrderParams,
getUserAccountPublicKeySync,
MainnetSpotMarkets,
numberToSafeBN,
PositionDirection,
PostOnlyParams,
PRICE_PRECISION,
QUOTE_PRECISION,
User,
type IWallet,
} from "@drift-labs/sdk";
import type { SolanaAgentKit } from "../../agent";
import * as anchor from "@coral-xyz/anchor";
import { IDL, VAULT_PROGRAM_ID, VaultClient } from "@drift-labs/vaults-sdk";
import { getAssociatedTokenAddressSync } from "@solana/spl-token";
import { PublicKey } from "@solana/web3.js";
import { Transaction } from "@solana/web3.js";
import { ComputeBudgetProgram } from "@solana/web3.js";
export async function initClients(
agent: SolanaAgentKit,
params?: {
authority: PublicKey;
activeSubAccountId: number;
subAccountIds: number[];
},
) {
const wallet: IWallet = {
publicKey: agent.wallet.publicKey,
payer: agent.wallet,
signAllTransactions: async (txs) => {
for (const tx of txs) {
tx.sign(agent.wallet);
}
return txs;
},
signTransaction: async (tx) => {
tx.sign(agent.wallet);
return tx;
},
};
// @ts-expect-error - false undefined type conflict
const driftClient = new DriftClient({
connection: agent.connection,
wallet,
env: "mainnet-beta",
authority: params?.authority,
activeSubAccountId: params?.activeSubAccountId,
subAccountIds: params?.subAccountIds,
txParams: {
computeUnitsPrice: 0.000001 * 1000000 * 1000000,
},
txSender: new FastSingleTxSender({
connection: agent.connection,
wallet,
timeout: 30000,
blockhashRefreshInterval: 1000,
opts: {
commitment: agent.connection.commitment ?? "confirmed",
skipPreflight: false,
preflightCommitment: agent.connection.commitment ?? "confirmed",
},
}),
});
const vaultProgram = new anchor.Program(
IDL,
VAULT_PROGRAM_ID,
driftClient.provider,
);
const vaultClient = new VaultClient({
driftClient,
// @ts-expect-error - type mismatch due to different dep versions
program: vaultProgram,
cliMode: false,
});
await driftClient.subscribe();
async function cleanUp() {
await driftClient.unsubscribe();
}
return { driftClient, vaultClient, cleanUp };
}
/**
* Create a drift user account provided an amount
* @param amount amount of the token to deposit
* @param symbol symbol of the token to deposit
*/
export async function createDriftUserAccount(
agent: SolanaAgentKit,
amount: number,
symbol: string,
) {
try {
const { driftClient, cleanUp } = await initClients(agent);
const user = new User({
driftClient,
userAccountPublicKey: getUserAccountPublicKeySync(
new PublicKey(DRIFT_PROGRAM_ID),
agent.wallet.publicKey,
),
});
const userAccountExists = await user.exists();
const token = MainnetSpotMarkets.find(
(v) => v.symbol === symbol.toUpperCase(),
);
if (!token) {
throw new Error(`Token with symbol ${symbol} not found`);
}
if (!userAccountExists) {
const depositAmount = numberToSafeBN(amount, token.precision);
const [txSignature, account] =
await driftClient.initializeUserAccountAndDepositCollateral(
depositAmount,
getAssociatedTokenAddressSync(token.mint, agent.wallet.publicKey),
);
await cleanUp();
return { txSignature, account };
}
await cleanUp();
return {
message: "User account already exists",
account: user.userAccountPublicKey,
};
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to create user account: ${e.message}`);
}
}
/**
* Deposit to your drift user account
* @param agent
* @param amount
* @param symbol
* @param isRepay
* @returns
*/
export async function depositToDriftUserAccount(
agent: SolanaAgentKit,
amount: number,
symbol: string,
isRepay = false,
) {
try {
const { driftClient, cleanUp } = await initClients(agent);
const publicKey = agent.wallet.publicKey;
const user = new User({
driftClient,
userAccountPublicKey: getUserAccountPublicKeySync(
new PublicKey(DRIFT_PROGRAM_ID),
publicKey,
),
});
const userAccountExists = await user.exists();
const token = MainnetSpotMarkets.find(
(v) => v.symbol === symbol.toUpperCase(),
);
if (!token) {
throw new Error(`Token with symbol ${symbol} not found`);
}
if (!userAccountExists) {
throw new Error("You need to create a Drift user account first.");
}
const depositAmount = numberToSafeBN(amount, token.precision);
const [depInstruction, latestBlockhash] = await Promise.all([
driftClient.getDepositTxnIx(
depositAmount,
token.marketIndex,
getAssociatedTokenAddressSync(token.mint, publicKey),
undefined,
isRepay,
),
driftClient.connection.getLatestBlockhash(),
]);
const tx = new Transaction().add(...depInstruction).add(
ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 0.000001 * 1000000 * 1000000,
}),
);
tx.recentBlockhash = latestBlockhash.blockhash;
tx.sign(agent.wallet);
const txSignature = await driftClient.txSender.sendRawTransaction(
tx.serialize(),
{ ...driftClient.opts },
);
await cleanUp();
return txSignature;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to deposit to user account: ${e.message}`);
}
}
export async function withdrawFromDriftUserAccount(
agent: SolanaAgentKit,
amount: number,
symbol: string,
isBorrow = false,
) {
try {
const { driftClient, cleanUp } = await initClients(agent);
const user = new User({
driftClient,
userAccountPublicKey: getUserAccountPublicKeySync(
new PublicKey(DRIFT_PROGRAM_ID),
agent.wallet.publicKey,
),
});
const userAccountExists = await user.exists();
if (!userAccountExists) {
throw new Error("You need to create a Drift user account first.");
}
const token = MainnetSpotMarkets.find(
(v) => v.symbol === symbol.toUpperCase(),
);
if (!token) {
throw new Error(`Token with symbol ${symbol} not found`);
}
const withdrawAmount = numberToSafeBN(amount, token.precision);
const [withdrawInstruction, latestBlockhash] = await Promise.all([
driftClient.getWithdrawalIxs(
withdrawAmount,
token.marketIndex,
getAssociatedTokenAddressSync(token.mint, agent.wallet.publicKey),
!isBorrow,
),
driftClient.connection.getLatestBlockhash(),
]);
const tx = new Transaction().add(...withdrawInstruction).add(
ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 0.000001 * 1000000 * 1000000,
}),
);
tx.recentBlockhash = latestBlockhash.blockhash;
tx.sign(agent.wallet);
const txSignature = await driftClient.txSender.sendRawTransaction(
tx.serialize(),
{ ...driftClient.opts },
);
await cleanUp();
return txSignature;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to withdraw from user account: ${e.message}`);
}
}
/**
* Open a perpetual trade on drift
* @param agent
* @param params.amount
* @param params.symbol
* @param params.action
* @param params.type
* @param params.price this should only be supplied if type is limit
* @param params.reduceOnly
*/
export async function driftPerpTrade(
agent: SolanaAgentKit,
params: {
amount: number;
symbol: string;
action: "long" | "short";
type: "market" | "limit";
price?: number | undefined;
},
) {
try {
const { driftClient, cleanUp } = await initClients(agent);
const user = new User({
driftClient,
userAccountPublicKey: getUserAccountPublicKeySync(
new PublicKey(DRIFT_PROGRAM_ID),
agent.wallet.publicKey,
),
});
const userAccountExists = await user.exists();
if (!userAccountExists) {
throw new Error("You need to create a Drift user account first.");
}
const market = driftClient.getMarketIndexAndType(
`${params.symbol.toUpperCase()}-PERP`,
);
if (!market) {
throw new Error(`Token with symbol ${params.symbol} not found`);
}
const baseAssetPrice = driftClient.getOracleDataForPerpMarket(
market.marketIndex,
);
const convertedAmount =
params.amount / convertToNumber(baseAssetPrice.price, PRICE_PRECISION);
let signature: anchor.web3.TransactionSignature;
if (params.type === "limit") {
if (!params.price) {
throw new Error("Price is required for limit orders");
}
signature = await driftClient.placePerpOrder(
getLimitOrderParams({
baseAssetAmount: numberToSafeBN(convertedAmount, BASE_PRECISION),
reduceOnly: false,
direction:
params.action === "long"
? PositionDirection.LONG
: PositionDirection.SHORT,
marketIndex: market.marketIndex,
price: numberToSafeBN(params.price, PRICE_PRECISION),
postOnly: PostOnlyParams.SLIDE,
}),
{
computeUnitsPrice: 0.000001 * 1000000 * 1000000,
},
);
} else {
signature = await driftClient.placePerpOrder(
getMarketOrderParams({
baseAssetAmount: numberToSafeBN(convertedAmount, BASE_PRECISION),
reduceOnly: false,
direction:
params.action === "long"
? PositionDirection.LONG
: PositionDirection.SHORT,
marketIndex: market.marketIndex,
}),
{
computeUnitsPrice: 0.000001 * 1000000 * 1000000,
},
);
}
if (!signature) {
throw new Error("Failed to place order. Please make sure ");
}
await cleanUp();
return signature;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to place order: ${e.message}`);
}
}
/**
* Check if a user has a drift account
* @param agent
*/
export async function doesUserHaveDriftAccount(agent: SolanaAgentKit) {
try {
const { driftClient, cleanUp } = await initClients(agent);
const user = new User({
driftClient,
userAccountPublicKey: getUserAccountPublicKeySync(
new PublicKey(DRIFT_PROGRAM_ID),
agent.wallet.publicKey,
),
});
user.getActivePerpPositions();
const userAccountExists = await user.exists();
await cleanUp();
return {
hasAccount: userAccountExists,
account: user.userAccountPublicKey,
};
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to check user account: ${e.message}`);
}
}
/**
* Get account info for a drift User
* @param agent
* @returns
*/
export async function driftUserAccountInfo(agent: SolanaAgentKit) {
try {
const { driftClient, cleanUp } = await initClients(agent);
const user = new User({
driftClient,
userAccountPublicKey: getUserAccountPublicKeySync(
new PublicKey(DRIFT_PROGRAM_ID),
agent.wallet.publicKey,
),
});
const userAccountExists = await user.exists();
if (!userAccountExists) {
throw new Error("User account does not exist");
}
await user.subscribe();
const account = user.getUserAccount();
await user.unsubscribe();
await cleanUp();
const perpPositions = account.perpPositions.map((pos) => ({
...pos,
baseAssetAmount: convertToNumber(pos.baseAssetAmount, BASE_PRECISION),
settledPnl: convertToNumber(pos.settledPnl, QUOTE_PRECISION),
}));
const spotPositions = account.spotPositions.map((pos) => ({
...pos,
scaledBalance: convertToNumber(pos.scaledBalance, BASE_PRECISION),
cumulativeDeposits: convertToNumber(
pos.cumulativeDeposits,
BASE_PRECISION,
),
symbol: MainnetSpotMarkets.find((v) => v.marketIndex === pos.marketIndex)
?.symbol,
}));
return {
...account,
name: account.name,
authority: account.authority,
totalDeposits: `$${convertToNumber(account.totalDeposits, QUOTE_PRECISION)}`,
totalWithdraws: `$${convertToNumber(account.totalWithdraws, QUOTE_PRECISION)}`,
settledPerpPnl: `$${convertToNumber(account.settledPerpPnl, QUOTE_PRECISION)}`,
lastActiveSlot: account.lastActiveSlot.toNumber(),
perpPositions,
spotPositions,
};
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to check user account: ${e.message}`);
}
}

View File

@@ -0,0 +1,641 @@
import {
BASE_PRECISION,
convertToNumber,
getLimitOrderParams,
getMarketOrderParams,
getOrderParams,
MainnetPerpMarkets,
MainnetSpotMarkets,
MarketType,
numberToSafeBN,
PERCENTAGE_PRECISION,
PositionDirection,
PostOnlyParams,
PRICE_PRECISION,
QUOTE_PRECISION,
TEN,
} from "@drift-labs/sdk";
import {
WithdrawUnit,
decodeName,
encodeName,
getVaultAddressSync,
getVaultDepositorAddressSync,
} from "@drift-labs/vaults-sdk";
import {
ComputeBudgetProgram,
PublicKey,
type TransactionInstruction,
} from "@solana/web3.js";
import type { SolanaAgentKit } from "../../agent";
import { BN } from "bn.js";
import { initClients } from "./drift";
export function getMarketIndexAndType(name: `${string}-${string}`) {
const [symbol, type] = name.toUpperCase().split("-");
if (type === "PERP") {
const token = MainnetPerpMarkets.find((v) => v.baseAssetSymbol === symbol);
if (!token) {
throw new Error("Drift doesn't have that market");
}
return { marketIndex: token.marketIndex, marketType: MarketType.PERP };
}
const token = MainnetSpotMarkets.find((v) => v.symbol === symbol);
if (!token) {
throw new Error("Drift doesn't have that market");
}
return { marketIndex: token.marketIndex, marketType: MarketType.SPOT };
}
async function getOrCreateVaultDepositor(agent: SolanaAgentKit, vault: string) {
const { vaultClient, cleanUp } = await initClients(agent);
const vaultPublicKey = new PublicKey(vault);
const vaultDepositor = getVaultDepositorAddressSync(
vaultClient.program.programId,
vaultPublicKey,
agent.wallet.publicKey,
);
try {
await vaultClient.getVaultDepositor(vaultDepositor);
await cleanUp();
return vaultDepositor;
} catch (e) {
// @ts-expect-error - error message is a string
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;
}
}
async function getVaultAvailableBalance(agent: SolanaAgentKit, vault: string) {
try {
const { cleanUp, vaultClient } = await initClients(agent);
const vaultDetails = await vaultClient.getVault(new PublicKey(vault));
const currentVaultBalance = convertToNumber(
vaultDetails.netDeposits,
QUOTE_PRECISION,
);
const vaultWithdrawalsRequested = convertToNumber(
vaultDetails.totalWithdrawRequested,
QUOTE_PRECISION,
);
const availableBalanceInUSD =
currentVaultBalance - vaultWithdrawalsRequested;
await cleanUp();
return availableBalanceInUSD;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to get vault available balance: ${e.message}`);
}
}
/**
Create a vault
@param agent SolanaAgentKit instance
@param params Vault creation parameters
@param params.name Name of the vault (must be unique)
@param params.marketName Market name of the vault (e.g. "USDC-SPOT")
@param params.redeemPeriod Redeem period in seconds
@param params.maxTokens Maximum amount that can be deposited into the vault (in tokens)
@param params.minDepositAmount Minimum amount that can be deposited into the vault (in tokens)
@param params.managementFee Management fee percentage (e.g 2 == 2%)
@param params.profitShare Profit share percentage (e.g 20 == 20%)
@param params.hurdleRate Hurdle rate percentage
@param params.permissioned Whether the vault uses a whitelist
@returns Promise<anchor.Web3.TransactionSignature> - The transaction signature of the vault creation
*/
export async function createVault(
agent: SolanaAgentKit,
params: {
name: string;
marketName: `${string}-${string}`;
redeemPeriod: number;
maxTokens: number;
minDepositAmount: number;
managementFee: number;
profitShare: number;
hurdleRate?: number;
permissioned?: boolean;
},
) {
try {
const { vaultClient, driftClient, cleanUp } = await initClients(agent);
const marketIndexAndType = getMarketIndexAndType(params.marketName);
if (!marketIndexAndType) {
throw new Error("Invalid market name");
}
const spotMarket = driftClient.getSpotMarketAccount(
marketIndexAndType.marketIndex,
);
if (!spotMarket) {
throw new Error("Market not found");
}
const spotPrecision = TEN.pow(new BN(spotMarket.decimals));
if (marketIndexAndType.marketType === MarketType.PERP) {
throw new Error("Only SPOT market names are supported");
}
const tx = await vaultClient.initializeVault({
name: encodeName(params.name),
spotMarketIndex: marketIndexAndType.marketIndex,
hurdleRate: new BN(params.hurdleRate ?? 0)
.mul(PERCENTAGE_PRECISION)
.div(new BN(100))
.toNumber(),
profitShare: new BN(params.profitShare)
.mul(PERCENTAGE_PRECISION)
.div(new BN(100))
.toNumber(),
minDepositAmount: numberToSafeBN(params.minDepositAmount, spotPrecision),
redeemPeriod: new BN(params.redeemPeriod * 86400),
maxTokens: numberToSafeBN(params.maxTokens, spotPrecision),
managementFee: new BN(params.managementFee)
.mul(PERCENTAGE_PRECISION)
.div(new BN(100)),
permissioned: params.permissioned ?? false,
});
await cleanUp();
return tx;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to create Drift vault: ${e.message}`);
}
}
export async function updateVaultDelegate(
agent: SolanaAgentKit,
vault: string,
delegateAddress: string,
) {
try {
const { vaultClient, cleanUp } = await initClients(agent);
const signature = await vaultClient.updateDelegate(
new PublicKey(vault),
new PublicKey(delegateAddress),
);
await cleanUp();
return signature;
} catch (e) {
throw new Error(
// @ts-expect-error - error message is a string
`Failed to update vault delegate: ${e.message}`,
);
}
}
/**
Update the vault's info
@param agent SolanaAgentKit instance
@param vault Vault address
@param params Vault update parameters
@param params.redeemPeriod Redeem period in seconds
@param params.maxTokens Maximum amount that can be deposited into the vault (in tokens)
@param params.minDepositAmount Minimum amount that can be deposited into the vault (in tokens)
@param params.managementFee Management fee percentage (e.g 2 == 2%)
@param params.profitShare Profit share percentage (e.g 20 == 20%)
@param params.hurdleRate Hurdle rate percentage
@param params.permissioned Whether the vault uses a whitelist
@returns Promise<anchor.Web3.TransactionSignature> - The transaction signature of the vault update
*/
export async function updateVault(
agent: SolanaAgentKit,
vault: string,
params: {
redeemPeriod?: number;
maxTokens?: number;
minDepositAmount?: number;
managementFee?: number;
profitShare?: number;
hurdleRate?: number;
permissioned?: boolean;
},
) {
try {
const { vaultClient, cleanUp, driftClient } = await initClients(agent);
const vaultPublicKey = new PublicKey(vault);
const vaultDetails = await vaultClient.getVault(vaultPublicKey);
const spotMarket = driftClient.getSpotMarketAccount(
vaultDetails.spotMarketIndex,
);
if (!spotMarket) {
throw new Error("Market not found");
}
const spotPrecision = TEN.pow(new BN(spotMarket.decimals));
const tx = await vaultClient.managerUpdateVault(vaultPublicKey, {
redeemPeriod: params.redeemPeriod
? new BN(params.redeemPeriod * 86400)
: null,
maxTokens: params.maxTokens
? numberToSafeBN(params.maxTokens, spotPrecision)
: null,
minDepositAmount: params.minDepositAmount
? numberToSafeBN(params.minDepositAmount, spotPrecision)
: null,
managementFee: params.managementFee
? new BN(params.managementFee)
.mul(PERCENTAGE_PRECISION)
.div(new BN(100))
: null,
profitShare: params.profitShare
? new BN(params.profitShare)
.mul(PERCENTAGE_PRECISION)
.div(new BN(100))
.toNumber()
: null,
hurdleRate: params.hurdleRate
? new BN(params.hurdleRate)
.mul(PERCENTAGE_PRECISION)
.div(new BN(100))
.toNumber()
: null,
permissioned: params.permissioned ?? vaultDetails.permissioned,
});
await cleanUp();
return tx;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to update Drift vault: ${e.message}`);
}
}
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 vaultNameOrAddress
* @returns
*/
export async function getVaultInfo(
agent: SolanaAgentKit,
vaultNameOrAddress: string,
) {
try {
const { vaultClient, cleanUp } = await initClients(agent);
const vaultPublicKey = validateAndEncodeAddress(
vaultNameOrAddress,
vaultClient.program.programId.toBase58(),
);
const [vaultDetails, vaultBalance] = await Promise.all([
vaultClient.getVault(vaultPublicKey),
getVaultAvailableBalance(agent, vaultPublicKey.toBase58()),
]);
await cleanUp();
const spotToken = MainnetSpotMarkets[vaultDetails.spotMarketIndex];
const data = {
name: decodeName(vaultDetails.name),
delegate: vaultDetails.delegate.toBase58(),
address: vaultPublicKey.toBase58(),
marketName: `${spotToken.symbol}-SPOT`,
balance: `${vaultBalance} ${spotToken.symbol}`,
redeemPeriod: vaultDetails.redeemPeriod.toNumber(),
maxTokens: vaultDetails.maxTokens.div(spotToken.precision).toNumber(),
minDepositAmount: vaultDetails.minDepositAmount
.div(spotToken.precision)
.toNumber(),
managementFee:
(vaultDetails.managementFee.toNumber() /
PERCENTAGE_PRECISION.toNumber()) *
100,
profitShare:
(vaultDetails.profitShare / PERCENTAGE_PRECISION.toNumber()) * 100,
hurdleRate:
(vaultDetails.hurdleRate / PERCENTAGE_PRECISION.toNumber()) * 100,
permissioned: vaultDetails.permissioned,
};
return data;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to get vault info: ${e.message}`);
}
}
/**
Deposit tokens into a vault
@param agent SolanaAgentKit instance
@param amount Amount to deposit into the vault (in tokens)
@param vault Vault address
@returns Promise<anchor.Web3.TransactionSignature> - The transaction signature of the deposit
*/
export async function depositIntoVault(
agent: SolanaAgentKit,
amount: number,
vault: string,
) {
const { vaultClient, driftClient, cleanUp } = await initClients(agent);
try {
const vaultPublicKey = new PublicKey(vault);
const [isOwned, vaultDetails, vaultDepositor] = await Promise.all([
getIsOwned(agent, vault),
vaultClient.getVault(vaultPublicKey),
getOrCreateVaultDepositor(agent, vault),
]);
const spotMarket = driftClient.getSpotMarketAccount(
vaultDetails.spotMarketIndex,
);
if (!spotMarket) {
throw new Error("Market not found");
}
const spotPrecision = TEN.pow(new BN(spotMarket.decimals));
const amountBN = numberToSafeBN(amount, spotPrecision);
if (isOwned) {
return await vaultClient.managerDeposit(vaultPublicKey, amountBN);
}
const tx = await vaultClient.deposit(vaultDepositor, amountBN);
await cleanUp();
return tx;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to deposit into Drift vault: ${e.message}`);
}
}
/**
Request a withdrawal from a vault. If successful redemption period starts and the user can redeem the tokens after the period ends
@param agent SolanaAgentKit instance
@param amount Amount to withdraw from the vault (in shares)
@param vault Vault address
*/
export async function requestWithdrawalFromVault(
agent: SolanaAgentKit,
amount: number,
vault: string,
) {
try {
const { vaultClient, cleanUp } = await initClients(agent);
const vaultPublicKey = new PublicKey(vault);
const isOwned = await getIsOwned(agent, vault);
if (isOwned) {
return await vaultClient.managerRequestWithdraw(
vaultPublicKey,
numberToSafeBN(amount, QUOTE_PRECISION),
WithdrawUnit.TOKEN,
);
}
const vaultDepositor = await getOrCreateVaultDepositor(agent, vault);
const tx = await vaultClient.requestWithdraw(
vaultDepositor,
numberToSafeBN(amount, QUOTE_PRECISION),
WithdrawUnit.TOKEN,
);
await cleanUp();
return tx;
} catch (e) {
throw new Error(
// @ts-expect-error - error message is a string
`Failed to request withdrawal from Drift vault: ${e.message}`,
);
}
}
/**
Withdraw tokens once the redemption period has elapsed.
@param agent SolanaAgentKit instance
@param vault Vault address
@returns Promise<anchor.Web3.TransactionSignature> - The transaction signature of the redemption
*/
export async function withdrawFromDriftVault(
agent: SolanaAgentKit,
vault: string,
) {
try {
const { vaultClient, cleanUp } = await initClients(agent);
const vaultPublicKey = new PublicKey(vault);
const isOwned = await getIsOwned(agent, vault);
if (isOwned) {
return await vaultClient.managerWithdraw(vaultPublicKey);
}
const vaultDepositor = await getOrCreateVaultDepositor(agent, vault);
const tx = await vaultClient.withdraw(vaultDepositor);
await cleanUp();
return tx;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to redeem tokens from Drift vault: ${e.message}`);
}
}
/**
Get if vault is owned by the user
@param agent SolanaAgentKit instance
@param vault Vault address
@returns Promise<boolean> - Whether the vault is owned by the user
*/
async function getIsOwned(agent: SolanaAgentKit, vault: string) {
try {
const { vaultClient, cleanUp } = await initClients(agent);
const vaultPublicKey = new PublicKey(vault);
const vaultDetails = await vaultClient.getVault(vaultPublicKey);
const isOwned = vaultDetails.manager.equals(agent.wallet.publicKey);
await cleanUp();
return isOwned;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to check if vault is owned: ${e.message}`);
}
}
/**
* Get a vaults address using the vault's name
* @param agent
* @param name
*/
export async function getVaultAddress(agent: SolanaAgentKit, name: string) {
const encodedName = encodeName(name);
try {
const { vaultClient, cleanUp } = await initClients(agent);
const vaultAddress = getVaultAddressSync(
vaultClient.program.programId,
encodedName,
);
await cleanUp();
return vaultAddress;
} catch (e) {
throw new Error(
// @ts-expect-error - error message is a string
`Failed to get vault address: ${e.message}`,
);
}
}
/**
Carry out a trade with a delegated vault
@param agent SolanaAgentKit instance
@param amount Amount to trade (in tokens)
@param symbol Symbol of the token to trade
@param action Action to take (e.g. "buy" or "sell")
@param type Type of trade (e.g. "market" or "limit")
@param vault Vault address
*/
export async function tradeDriftVault(
agent: SolanaAgentKit,
vault: string,
amount: number,
symbol: string,
action: "long" | "short",
type: "market" | "limit",
price?: number,
) {
try {
const { driftClient, cleanUp } = await initClients(agent, {
authority: new PublicKey(vault),
activeSubAccountId: 0,
subAccountIds: [0],
});
const [isOwned, driftLookupTableAccount] = await Promise.all([
getIsOwned(agent, vault),
driftClient.fetchMarketLookupTableAccount(),
]);
if (!isOwned) {
throw new Error(
"This vault is owned by someone else, so you can't trade with it",
);
}
const usdcSpotMarket = driftClient.getSpotMarketAccount(0);
if (!usdcSpotMarket) {
throw new Error("USDC-SPOT market not found");
}
const perpMarketIndexAndType = getMarketIndexAndType(
`${symbol.toUpperCase()}-PERP`,
);
const perpMarketAccount = driftClient.getPerpMarketAccount(
perpMarketIndexAndType.marketIndex,
);
if (!perpMarketIndexAndType || !perpMarketAccount) {
throw new Error(
"Invalid symbol: Drift doesn't have a market for this token",
);
}
const perpOracle = driftClient.getOracleDataForPerpMarket(
perpMarketAccount.marketIndex,
);
const oraclePriceNumber = convertToNumber(
perpOracle.price,
PRICE_PRECISION,
);
const baseAmount = amount / oraclePriceNumber;
const instructions: TransactionInstruction[] = [];
instructions.push(
ComputeBudgetProgram.setComputeUnitLimit({ units: 1400000 }),
);
if (type === "limit" || price) {
if (!price) {
throw new Error("Price is required for limit orders");
}
const instruction = await driftClient.getPlaceOrdersIx([
getOrderParams(
getLimitOrderParams({
price: numberToSafeBN(price, PRICE_PRECISION),
marketType: MarketType.PERP,
baseAssetAmount: numberToSafeBN(baseAmount, BASE_PRECISION),
direction:
action === "long"
? PositionDirection.LONG
: PositionDirection.SHORT,
marketIndex: perpMarketAccount.marketIndex,
postOnly: PostOnlyParams.SLIDE,
}),
),
]);
instructions.push(instruction);
} else {
// defaults to market order if type is not limit and price is not provided
const instruction = await driftClient.getPlaceOrdersIx([
getOrderParams(
getMarketOrderParams({
marketType: MarketType.PERP,
baseAssetAmount: numberToSafeBN(baseAmount, BASE_PRECISION),
direction:
action === "long"
? PositionDirection.LONG
: PositionDirection.SHORT,
marketIndex: perpMarketAccount.marketIndex,
}),
),
]);
instructions.push(instruction);
}
const latestBlockhash = await driftClient.connection.getLatestBlockhash();
const tx = await driftClient.txSender.sendVersionedTransaction(
await driftClient.txSender.getVersionedTransaction(
instructions,
[driftLookupTableAccount],
[],
driftClient.opts,
latestBlockhash,
),
);
await cleanUp();
return tx;
} catch (e) {
// @ts-expect-error - error message is a string
throw new Error(`Failed to trade with Drift vault: ${e.message}`);
}
}

2
src/tools/drift/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export * from "./drift";
export * from "./drift_vault";

View File

@@ -1,7 +1,7 @@
import { ComputeBudgetProgram } from "@solana/web3.js";
import { PoolConfig, Side } from "flash-sdk";
import { BN } from "@coral-xyz/anchor";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import {
CLOSE_POSITION_CU,
marketSdkInfo,
@@ -10,8 +10,8 @@ import {
fetchOraclePrice,
createPerpClient,
get_flash_privilege,
} from "../utils/flashUtils";
import { FlashCloseTradeParams } from "../types";
} from "../../utils/flashUtils";
import { FlashCloseTradeParams } from "../../types";
/**
* Closes an existing position on Flash.Trade

View File

@@ -8,7 +8,7 @@ import {
Custody,
} from "flash-sdk";
import { BN } from "@coral-xyz/anchor";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import {
ALL_TOKENS,
marketSdkInfo,
@@ -18,8 +18,8 @@ import {
fetchOraclePrice,
createPerpClient,
get_flash_privilege,
} from "../utils/flashUtils";
import { FlashTradeParams } from "../types";
} from "../../utils/flashUtils";
import { FlashTradeParams } from "../../types";
/**
* Opens a new position on Flash.Trade

2
src/tools/flash/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export * from "./flash_open_trade";
export * from "./flash_close_trade";

View File

@@ -1,6 +1,6 @@
import { VersionedTransaction } from "@solana/web3.js";
import { PublicKey } from "@solana/web3.js";
import { GibworkCreateTaskReponse, SolanaAgentKit } from "../index";
import { GibworkCreateTaskReponse, SolanaAgentKit } from "../../index";
/**
* Create an new task on Gibwork

View File

@@ -0,0 +1 @@
export * from "./create_gibwork_task";

View File

@@ -0,0 +1,57 @@
import { SolanaAgentKit } from "../../index";
import { PublicKey } from "@solana/web3.js";
/**
* Fetch assets by owner using the Helius Digital Asset Standard (DAS) API
* @param agent SolanaAgentKit instance
* @param ownerPublicKey Owner's Solana wallet PublicKey
* @param limit Number of assets to retrieve per request
* @returns Assets owned by the specified address
*/
export async function getAssetsByOwner(
agent: SolanaAgentKit,
ownerPublicKey: PublicKey,
limit: number,
): Promise<any> {
try {
const apiKey = agent.config.HELIUS_API_KEY;
if (!apiKey) {
throw new Error("HELIUS_API_KEY not found in environment variables");
}
const url = `https://mainnet.helius-rpc.com/?api-key=${apiKey}`;
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: "get-assets",
method: "getAssetsByOwner",
params: {
ownerAddress: ownerPublicKey.toString(),
page: 3,
limit: limit,
displayOptions: {
showFungible: true,
},
},
}),
});
if (!response.ok) {
throw new Error(
`Failed to fetch: ${response.status} - ${response.statusText}`,
);
}
const data = await response.json();
return data.result.items;
} catch (error: any) {
console.error("Error retrieving assets: ", error.message);
throw new Error(`Assets retrieval failed: ${error.message}`);
}
}

View File

@@ -0,0 +1,44 @@
import { SolanaAgentKit } from "../../index";
/**
* Parse a Solana transaction using the Helius Enhanced Transactions API
* @param agent SolanaAgentKit instance
* @param transactionId The transaction ID to parse
* @returns Parsed transaction data
*/
export async function parseTransaction(
agent: SolanaAgentKit,
transactionId: string,
): Promise<any> {
try {
const apiKey = agent.config.HELIUS_API_KEY;
if (!apiKey) {
throw new Error("HELIUS_API_KEY not found in environment variables");
}
const url = `https://api.helius.xyz/v0/transactions/?api-key=${apiKey}`;
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
transactions: [transactionId],
}),
});
if (!response.ok) {
throw new Error(
`Failed to fetch: ${response.status} - ${response.statusText}`,
);
}
const data = await response.json();
return data;
} catch (error: any) {
console.error("Error parsing transaction: ", error.message);
throw new Error(`Transaction parsing failed: ${error.message}`);
}
}

View File

@@ -0,0 +1,132 @@
import { SolanaAgentKit } from "../../index";
import { HeliusWebhookResponse, HeliusWebhookIdResponse } from "../../index";
export async function create_HeliusWebhook(
agent: SolanaAgentKit,
accountAddresses: string[],
webhookURL: string,
): Promise<HeliusWebhookResponse> {
try {
const response = await fetch(
`https://api.helius.xyz/v0/webhooks?api-key=${agent.config.HELIUS_API_KEY}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
webhookURL,
transactionTypes: ["Any"],
accountAddresses,
webhookType: "enhanced",
txnStatus: "all",
}),
},
);
const data = await response.json();
return {
webhookURL: data.webhookURL,
webhookID: data.webhookID,
};
} catch (error: any) {
throw new Error(`Failed to create Webhook: ${error.message}`);
}
}
/**
* Retrieves a Helius Webhook by ID, returning only the specified fields.
*
* @param agent - An instance of SolanaAgentKit (with .config.HELIUS_API_KEY)
* @param webhookID - The unique ID of the webhook to retrieve
*
* @returns A HeliusWebhook object containing { wallet, webhookURL, transactionTypes, accountAddresses, webhookType }
*/
export async function getHeliusWebhook(
agent: SolanaAgentKit,
webhookID: string,
): Promise<HeliusWebhookIdResponse> {
try {
const apiKey = agent.config.HELIUS_API_KEY;
if (!apiKey) {
throw new Error("HELIUS_API_KEY is missing in agent.config");
}
const response = await fetch(
`https://api.helius.xyz/v0/webhooks/${webhookID}?api-key=${apiKey}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
},
);
if (!response.ok) {
throw new Error(
`Failed to fetch webhook with ID ${webhookID}. ` +
`Status Code: ${response.status}`,
);
}
const data = await response.json();
return {
wallet: data.wallet,
webhookURL: data.webhookURL,
transactionTypes: data.transactionTypes,
accountAddresses: data.accountAddresses,
webhookType: data.webhookType,
};
} catch (error: any) {
throw new Error(`Failed to get webhook by ID: ${error.message}`);
}
}
/**
* Deletes a Helius Webhook by its ID.
*
* @param agent - An instance of SolanaAgentKit (with .config.HELIUS_API_KEY)
* @param webhookID - The unique ID of the webhook to delete
*
* @returns The response body from the Helius API (which may contain status or other info)
*/
export async function deleteHeliusWebhook(
agent: SolanaAgentKit,
webhookID: string,
): Promise<any> {
try {
const apiKey = agent.config.HELIUS_API_KEY;
if (!apiKey) {
throw new Error("Missing Helius API key in agent.config.HELIUS_API_KEY");
}
const url = `https://api.helius.xyz/v0/webhooks/${webhookID}?api-key=${apiKey}`;
const response = await fetch(url, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(
`Failed to delete webhook: ${response.status} ${response.statusText}`,
);
}
if (response.status === 204) {
return { message: "Webhook deleted successfully (no content returned)" };
}
const contentLength = response.headers.get("Content-Length");
if (contentLength === "0" || !contentLength) {
return { message: "Webhook deleted successfully (empty body)" };
}
// Otherwise, parse as JSON
const data = await response.json();
return data;
} catch (error: any) {
console.error("Error deleting Helius Webhook:", error.message);
throw new Error(`Failed to delete Helius Webhook: ${error.message}`);
}
}

View File

@@ -0,0 +1,4 @@
export * from "./get_assets_by_owner";
export * from "./helius_transaction_parsing";
export * from "./helius_webhooks";
export * from "./send_transaction_with_priority";

View File

@@ -0,0 +1,174 @@
import { SolanaAgentKit, PriorityFeeResponse } from "../../index";
import {
SystemProgram,
Transaction,
sendAndConfirmTransaction,
ComputeBudgetProgram,
PublicKey,
LAMPORTS_PER_SOL,
} from "@solana/web3.js";
import {
getAssociatedTokenAddress,
createTransferInstruction,
getMint,
createAssociatedTokenAccountInstruction,
} from "@solana/spl-token";
import bs58 from "bs58";
/**
* Sends a transaction with an estimated priority fee using the provided SolanaAgentKit.
*
* @param agent An instance of SolanaAgentKit containing connection, wallet, etc.
* @param priorityLevel The priority level (e.g., "Min", "Low", "Medium", "High", "VeryHigh", or "UnsafeMax").
* @param amount The amount of SOL to send (in SOL, not lamports).
* @param to The recipient's PublicKey.
* @returns The transaction signature (string) once confirmed along with the fee used.
*/
export async function sendTransactionWithPriorityFee(
agent: SolanaAgentKit,
priorityLevel: string,
amount: number,
to: PublicKey,
splmintAddress?: PublicKey,
): Promise<{ transactionId: string; fee: number }> {
try {
if (!splmintAddress) {
const transaction = new Transaction();
const { blockhash, lastValidBlockHeight } =
await agent.connection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.lastValidBlockHeight = lastValidBlockHeight;
transaction.feePayer = agent.wallet_address;
const transferIx = SystemProgram.transfer({
fromPubkey: agent.wallet_address,
toPubkey: to,
lamports: amount * LAMPORTS_PER_SOL,
});
transaction.add(transferIx);
transaction.sign(agent.wallet);
const response = await fetch(
`https://mainnet.helius-rpc.com/?api-key=${agent.config.HELIUS_API_KEY}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "getPriorityFeeEstimate",
params: [
{
transaction: bs58.encode(transaction.serialize()),
options: { priorityLevel: priorityLevel },
},
],
} as PriorityFeeResponse),
},
);
const data = await response.json();
if (data.error) {
throw new Error("Error fetching priority fee:");
}
const feeEstimate: number = data.result.priorityFeeEstimate;
// Set the priority fee if applicable
const computePriceIx = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: feeEstimate,
});
transaction.add(computePriceIx);
// Send the transaction and confirm
const txSignature = await sendAndConfirmTransaction(
agent.connection,
transaction,
[agent.wallet],
);
return {
transactionId: txSignature,
fee: feeEstimate,
};
} else {
const fromAta = await getAssociatedTokenAddress(
splmintAddress,
agent.wallet_address,
);
const toAta = await getAssociatedTokenAddress(splmintAddress, to);
const mintInfo = await getMint(agent.connection, splmintAddress);
const adjustedAmount = amount * Math.pow(10, mintInfo.decimals);
const transaction = new Transaction();
const { blockhash, lastValidBlockHeight } =
await agent.connection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.lastValidBlockHeight = lastValidBlockHeight;
transaction.feePayer = agent.wallet_address;
const response = await fetch(
`https://mainnet.helius-rpc.com/?api-key=${agent.config.HELIUS_API_KEY}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "getPriorityFeeEstimate",
params: [
{
transaction: bs58.encode(transaction.serialize()),
options: { priorityLevel: priorityLevel },
},
],
} as PriorityFeeResponse),
},
);
const data = await response.json();
if (data.error) {
throw new Error("Error fetching priority fee:");
}
const feeEstimate: number = data.result.priorityFeeEstimate;
transaction.add(
ComputeBudgetProgram.setComputeUnitPrice({
microLamports: feeEstimate,
}),
);
transaction.add(
createAssociatedTokenAccountInstruction(
agent.wallet_address,
toAta,
to,
splmintAddress,
),
);
transaction.add(
createTransferInstruction(
fromAta,
toAta,
agent.wallet_address,
adjustedAmount,
),
);
const txSignature = await sendAndConfirmTransaction(
agent.connection,
transaction,
[agent.wallet],
);
return {
transactionId: txSignature,
fee: feeEstimate,
};
}
} catch (error: any) {
throw new Error(`Failed to process transaction: ${error.message}`);
}
}

View File

@@ -1,52 +1,27 @@
export * from "./adrena_perp_trading";
export * from "./create_gibwork_task";
export * from "./create_image";
export * from "./create_tiplinks";
export * from "./deploy_collection";
export * from "./deploy_token";
export * from "./fetch_price";
export * from "./get_all_domains_tlds";
export * from "./get_all_registered_all_domains";
export * from "./get_balance";
export * from "./get_balance_other";
export * from "./get_main_all_domains_domain";
export * from "./get_owned_all_domains";
export * from "./get_owned_domains_for_tld";
export * from "./get_primary_domain";
export * from "./get_token_data";
export * from "./get_tps";
export * from "./get_wallet_address";
export * from "./launch_pumpfun_token";
export * from "./lend";
export * from "./manifest_trade";
export * from "./mint_nft";
export * from "./openbook_create_market";
export * from "./orca_close_position";
export * from "./orca_create_clmm";
export * from "./orca_create_single_sided_liquidity_pool";
export * from "./orca_fetch_positions";
export * from "./orca_open_centered_position_with_liquidity";
export * from "./orca_open_single_sided_position";
export * from "./pyth_fetch_price";
export * from "./raydium_create_ammV4";
export * from "./raydium_create_clmm";
export * from "./raydium_create_cpmm";
export * from "./register_domain";
export * from "./request_faucet_funds";
export * from "./resolve_domain";
export * from "./resolve_sol_domain";
export * from "./rock_paper_scissor";
export * from "./adrena";
export * from "./sns";
export * from "./dexscreener";
export * from "./alldomains";
export * from "./flash";
export * from "./gibwork";
export * from "./jupiter";
export * from "./lulo";
export * from "./manifest";
export * from "./solana";
export * from "./agent";
export * from "./metaplex";
export * from "./openbook";
export * from "./orca";
export * from "./pumpfun";
export * from "./pyth";
export * from "./raydium";
export * from "./rugcheck";
export * from "./send_compressed_airdrop";
export * from "./stake_with_jup";
export * from "./stake_with_solayer";
export * from "./tensor_trade";
export * from "./close_empty_token_accounts";
export * from "./trade";
export * from "./transfer";
export * from "./flash_open_trade";
export * from "./flash_close_trade";
export * from "./create_3land_collectible";
export * from "./drift";
export * from "./sendarcade";
export * from "./solayer";
export * from "./tensor";
export * from "./3land";
export * from "./tiplink";
export * from "./lightprotocol";
export * from "./squads";
export * from "./helius";

View File

@@ -0,0 +1,3 @@
export * from "./fetch_price";
export * from "./stake_with_jup";
export * from "./trade";

View File

@@ -1,5 +1,5 @@
import { VersionedTransaction } from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
/**
* Stake SOL with Jup validator

View File

@@ -1,11 +1,11 @@
import { VersionedTransaction, PublicKey } from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import {
TOKENS,
DEFAULT_OPTIONS,
JUP_API,
JUP_REFERRAL_ADDRESS,
} from "../constants";
} from "../../constants";
import { getMint } from "@solana/spl-token";
/**
* Swap tokens using Jupiter Exchange

View File

@@ -0,0 +1 @@
export * from "./send_compressed_airdrop";

View File

@@ -5,7 +5,7 @@ import {
PublicKey,
TransactionInstruction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import {
buildAndSignTx,
calculateComputeUnitPrice,

1
src/tools/lulo/index.ts Normal file
View File

@@ -0,0 +1 @@
export * from "./lend";

View File

@@ -1,5 +1,5 @@
import { VersionedTransaction } from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
/**
* Lend tokens for yields using Lulo

View File

@@ -0,0 +1 @@
export * from "./manifest_trade";

View File

@@ -11,7 +11,7 @@ import {
Transaction,
TransactionInstruction,
} from "@solana/web3.js";
import { BatchOrderPattern, OrderParams, SolanaAgentKit } from "../index";
import { BatchOrderPattern, OrderParams, SolanaAgentKit } from "../../index";
export async function manifestCreateMarket(
agent: SolanaAgentKit,

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import {
generateSigner,
keypairIdentity,
@@ -9,7 +9,7 @@ import {
mplCore,
ruleSet,
} from "@metaplex-foundation/mpl-core";
import { CollectionOptions, CollectionDeployment } from "../types";
import { CollectionOptions, CollectionDeployment } from "../../types";
import {
fromWeb3JsKeypair,
toWeb3JsPublicKey,

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import { PublicKey } from "@solana/web3.js";
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
import { generateSigner, keypairIdentity } from "@metaplex-foundation/umi";

View File

@@ -0,0 +1,3 @@
export * from "./deploy_collection";
export * from "./mint_nft";
export * from "./deploy_token";

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import { generateSigner, keypairIdentity } from "@metaplex-foundation/umi";
import { create, mplCore } from "@metaplex-foundation/mpl-core";
import { fetchCollection } from "@metaplex-foundation/mpl-core";
@@ -9,7 +9,7 @@ import {
toWeb3JsPublicKey,
} from "@metaplex-foundation/umi-web3js-adapters";
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
import { MintCollectionNFTResponse } from "../types";
import { MintCollectionNFTResponse } from "../../types";
/**
* Mint a new NFT as part of an existing collection

View File

@@ -0,0 +1 @@
export * from "./openbook_create_market";

View File

@@ -5,7 +5,7 @@ import {
} from "@raydium-io/raydium-sdk-v2";
import { MintLayout, TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { PublicKey } from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
export async function openbookCreateMarket(
agent: SolanaAgentKit,

6
src/tools/orca/index.ts Normal file
View File

@@ -0,0 +1,6 @@
export * from "./orca_close_position";
export * from "./orca_create_clmm";
export * from "./orca_create_single_sided_liquidity_pool";
export * from "./orca_fetch_positions";
export * from "./orca_open_centered_position_with_liquidity";
export * from "./orca_open_single_sided_position";

View File

@@ -4,15 +4,15 @@ import {
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../agent";
import { Wallet } from "@coral-xyz/anchor";
import { SolanaAgentKit } from "../../agent";
import { Wallet } from "../../utils/keypair";
import {
ORCA_WHIRLPOOL_PROGRAM_ID,
WhirlpoolContext,
buildWhirlpoolClient,
PDAUtil,
} from "@orca-so/whirlpools-sdk";
import { sendTx } from "../utils/send_tx";
import { sendTx } from "../../utils/send_tx";
import { Percentage } from "@orca-so/common-sdk";
/**

View File

@@ -4,8 +4,8 @@ import {
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../agent";
import { Wallet } from "@coral-xyz/anchor";
import { SolanaAgentKit } from "../../agent";
import { Wallet } from "../../utils/keypair";
import { Decimal } from "decimal.js";
import {
ORCA_WHIRLPOOL_PROGRAM_ID,
@@ -14,7 +14,7 @@ import {
PoolUtil,
buildWhirlpoolClient,
} from "@orca-so/whirlpools-sdk";
import { sendTx } from "../utils/send_tx";
import { sendTx } from "../../utils/send_tx";
import { FEE_TIERS } from "./orca_create_single_sided_liquidity_pool";
/**

View File

@@ -4,8 +4,9 @@ import {
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../agent";
import { BN, Wallet } from "@coral-xyz/anchor";
import { SolanaAgentKit } from "../../agent";
import { BN } from "@coral-xyz/anchor";
import { Wallet } from "../../utils/keypair";
import { Decimal } from "decimal.js";
import {
PDAUtil,
@@ -36,7 +37,7 @@ import {
getAssociatedTokenAddressSync,
TOKEN_2022_PROGRAM_ID,
} from "@solana/spl-token";
import { sendTx } from "../utils/send_tx";
import { sendTx } from "../../utils/send_tx";
/**
* Maps fee tier bps to their corresponding tick spacing values in the Orca Whirlpool protocol.

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../agent";
import { SolanaAgentKit } from "../../agent";
import { Wallet } from "@coral-xyz/anchor";
import {
ORCA_WHIRLPOOL_PROGRAM_ID,

View File

@@ -5,8 +5,8 @@ import {
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../agent";
import { Wallet } from "@coral-xyz/anchor";
import { SolanaAgentKit } from "../../agent";
import { Wallet } from "../../utils/keypair";
import { Decimal } from "decimal.js";
import {
ORCA_WHIRLPOOL_PROGRAM_ID,
@@ -18,7 +18,7 @@ import {
NO_TOKEN_EXTENSION_CONTEXT,
} from "@orca-so/whirlpools-sdk";
import { sendTx } from "../utils/send_tx";
import { sendTx } from "../../utils/send_tx";
import { Percentage } from "@orca-so/common-sdk";
import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";

View File

@@ -1,11 +1,12 @@
import {
Keypair,
PublicKey,
TransactionInstruction,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../agent";
import { Wallet } from "@coral-xyz/anchor";
import { SolanaAgentKit } from "../../agent";
import { Wallet } from "../../utils/keypair";
import { Decimal } from "decimal.js";
import {
ORCA_WHIRLPOOL_PROGRAM_ID,
@@ -16,7 +17,7 @@ import {
TokenExtensionContextForPool,
NO_TOKEN_EXTENSION_CONTEXT,
} from "@orca-so/whirlpools-sdk";
import { sendTx } from "../utils/send_tx";
import { sendTx } from "../../utils/send_tx";
import { Percentage } from "@orca-so/common-sdk";
import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";
@@ -119,17 +120,17 @@ export async function orcaOpenSingleSidedPosition(
lowerTick,
upperTick,
]);
let txIds: string = "";
let instructions: TransactionInstruction[] = [];
let signers: Keypair[] = [];
if (txBuilderTickArrays !== null) {
const txPayloadTickArrays = await txBuilderTickArrays.build();
const txPayloadTickArraysDecompiled = TransactionMessage.decompile(
(txPayloadTickArrays.transaction as VersionedTransaction).message,
);
const instructions = txPayloadTickArraysDecompiled.instructions;
const signers = txPayloadTickArrays.signers as Keypair[];
const tickArrayTxId = await sendTx(agent, instructions, signers);
txIds += tickArrayTxId + ",";
instructions = instructions.concat(
txPayloadTickArraysDecompiled.instructions,
);
signers = signers.concat(txPayloadTickArrays.signers as Keypair[]);
}
const tokenExtensionCtx: TokenExtensionContextForPool = {
@@ -161,14 +162,13 @@ export async function orcaOpenSingleSidedPosition(
const txPayloadDecompiled = TransactionMessage.decompile(
(txPayload.transaction as VersionedTransaction).message,
);
const instructions = txPayloadDecompiled.instructions;
const signers = txPayload.signers as Keypair[];
instructions = instructions.concat(txPayloadDecompiled.instructions);
signers = signers.concat(txPayload.signers as Keypair[]);
const positionTxId = await sendTx(agent, instructions, signers);
txIds += positionTxId;
const txId = await sendTx(agent, instructions, signers);
return JSON.stringify({
transactionIds: txIds,
transactionIds: txId,
positionMint: positionMint.toString(),
});
} catch (error) {

View File

@@ -0,0 +1 @@
export * from "./launch_pumpfun_token";

View File

@@ -4,7 +4,7 @@ import {
PumpfunLaunchResponse,
PumpFunTokenOptions,
SolanaAgentKit,
} from "../index";
} from "../../index";
async function uploadMetadata(
tokenName: string,

1
src/tools/pyth/index.ts Normal file
View File

@@ -0,0 +1 @@
export * from "./pyth_fetch_price";

View File

@@ -1,5 +1,5 @@
import BN from "bn.js";
import { PythPriceFeedIDItem } from "../types";
import { PythPriceFeedIDItem } from "../../types";
/**
* Fetch the price feed ID for a given token symbol from Pyth

View File

@@ -0,0 +1,3 @@
export * from "./raydium_create_ammV4";
export * from "./raydium_create_clmm";
export * from "./raydium_create_cpmm";

View File

@@ -9,7 +9,7 @@ import {
import { MintLayout, TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
export async function raydiumCreateAmmV4(
agent: SolanaAgentKit,

View File

@@ -7,7 +7,7 @@ import { MintLayout } from "@solana/spl-token";
import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";
import Decimal from "decimal.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
export async function raydiumCreateClmm(
agent: SolanaAgentKit,

View File

@@ -7,7 +7,7 @@ import {
import { MintLayout } from "@solana/spl-token";
import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
export async function raydiumCreateCpmm(
agent: SolanaAgentKit,

View File

@@ -0,0 +1 @@
export * from "./rugcheck";

View File

@@ -1,4 +1,4 @@
import { TokenCheck } from "../types";
import { TokenCheck } from "../../types";
const BASE_URL = "https://api.rugcheck.xyz/v1";

View File

@@ -0,0 +1 @@
export * from "./rock_paper_scissor";

View File

@@ -1,5 +1,5 @@
import { sendAndConfirmTransaction, Transaction } from "@solana/web3.js";
import { SolanaAgentKit } from "../agent";
import { SolanaAgentKit } from "../../agent";
export async function rock_paper_scissor(
agent: SolanaAgentKit,

View File

@@ -1,7 +1,7 @@
import { getAllDomains } from "@bonfida/spl-name-service";
import { SolanaAgentKit } from "../agent";
import { SolanaAgentKit } from "../../agent";
import { PublicKey } from "@solana/web3.js";
import { getAllDomainsTLDs } from "./get_all_domains_tlds";
import { getAllDomainsTLDs } from "../alldomains/get_all_domains_tlds";
/**
* Get all registered domains across all TLDs

View File

@@ -1,6 +1,6 @@
import { getPrimaryDomain as _getPrimaryDomain } from "@bonfida/spl-name-service";
import { PublicKey } from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../agent";
/**
* Retrieves the primary .sol domain associated with a given Solana public key.

5
src/tools/sns/index.ts Normal file
View File

@@ -0,0 +1,5 @@
export * from "./get_all_registered_all_domains";
export * from "./get_main_all_domains_domain";
export * from "./get_primary_domain";
export * from "./register_domain";
export * from "./resolve_sol_domain";

View File

@@ -1,8 +1,8 @@
import { registerDomainNameV2 } from "@bonfida/spl-name-service";
import { Transaction } from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../agent";
import { getAssociatedTokenAddressSync } from "@solana/spl-token";
import { TOKENS } from "../constants";
import { TOKENS } from "../../constants";
/**
* Register a .sol domain name using Bonfida Name Service

View File

@@ -1,6 +1,6 @@
import { resolve } from "@bonfida/spl-name-service";
import { PublicKey } from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
/**
* Resolves a .sol domain to a Solana PublicKey.

View File

@@ -3,7 +3,7 @@ import {
Transaction,
TransactionInstruction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../agent";
import { SolanaAgentKit } from "../../agent";
import {
AccountLayout,
createCloseAccountInstruction,

View File

@@ -1,5 +1,5 @@
import { LAMPORTS_PER_SOL, type PublicKey } from "@solana/web3.js";
import type { SolanaAgentKit } from "../index";
import { LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js";
import { SolanaAgentKit } from "../../index";
/**
* Get the balance of SOL or an SPL token for the agent's wallet

View File

@@ -3,7 +3,7 @@ import {
ParsedAccountData,
PublicKey,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
/**
* Get the balance of SOL or an SPL token for the specified wallet address (other than the agent's wallet)

View File

@@ -1,7 +1,7 @@
import { LAMPORTS_PER_SOL, type PublicKey } from "@solana/web3.js";
import type { SolanaAgentKit } from "../index";
import type { SolanaAgentKit } from "../../index";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { getTokenMetadata } from "../utils/tokenMetadata";
import { getTokenMetadata } from "../../utils/tokenMetadata";
/**
* Get the token balances of a Solana wallet

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
export async function getTPS(agent: SolanaAgentKit): Promise<number> {
const perfSamples = await agent.connection.getRecentPerformanceSamples();

View File

@@ -0,0 +1,7 @@
export * from "./get_tps";
export * from "./request_faucet_funds";
export * from "./close_empty_token_accounts";
export * from "./transfer";
export * from "./get_balance";
export * from "./get_balance_other";
export * from "./get_token_balances";

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import { LAMPORTS_PER_SOL } from "@solana/web3.js";
/**

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import { PublicKey, SystemProgram, Transaction } from "@solana/web3.js";
import { LAMPORTS_PER_SOL } from "@solana/web3.js";
import {

View File

@@ -0,0 +1 @@
export * from "./stake_with_solayer";

View File

@@ -1,5 +1,5 @@
import { VersionedTransaction } from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
/**
* Stake SOL with Solayer

View File

@@ -10,7 +10,7 @@ const { Multisig } = multisig.accounts;
* @returns {Promise<string>} - A promise that resolves to the transaction ID of the approved proposal.
* @throws {Error} - Throws an error if the approval process fails.
*/
export async function approve_proposal(
export async function multisig_approve_proposal(
agent: SolanaAgentKit,
transactionIndex?: number | bigint,
): Promise<string> {

View File

@@ -17,7 +17,6 @@ export async function create_squads_multisig(
): Promise<string> {
const connection = agent.connection;
const createKey = agent.wallet; // can be any keypair, using the agent wallet as only one multisig is required
console.log("Multisig Create Key:", createKey.publicKey.toBase58());
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,

View File

@@ -10,7 +10,7 @@ const { Multisig } = multisig.accounts;
* @returns {Promise<string>} - The transaction ID of the created proposal.
* @throws {Error} - Throws an error if the proposal creation fails.
*/
export async function create_proposal(
export async function multisig_create_proposal(
agent: SolanaAgentKit,
transactionIndex?: number | bigint,
): Promise<string> {

View File

@@ -17,7 +17,7 @@ import * as multisig from "@sqds/multisig";
* @param mint Optional mint address for SPL tokens
* @returns Transaction signature
*/
export async function deposit_to_multisig(
export async function multisig_deposit_to_treasury(
agent: SolanaAgentKit,
amount: number,
vaultIndex?: number,

View File

@@ -10,7 +10,7 @@ const { Multisig } = multisig.accounts;
* @returns {Promise<string>} - A promise that resolves to the transaction signature string.
* @throws {Error} - Throws an error if the transaction execution fails.
*/
export async function execute_transaction(
export async function multisig_execute_proposal(
agent: SolanaAgentKit,
transactionIndex?: number | bigint,
): Promise<string> {

View File

@@ -0,0 +1,7 @@
export * from "./create_multisig";
export * from "./create_proposal";
export * from "./approve_proposal";
export * from "./deposit_to_treasury";
export * from "./execute_proposal";
export * from "./reject_proposal";
export * from "./transfer_from_treasury";

View File

@@ -10,7 +10,7 @@ const { Multisig } = multisig.accounts;
* @returns A promise that resolves to the transaction ID of the rejection transaction.
* @throws Will throw an error if the transaction fails.
*/
export async function reject_proposal(
export async function multisig_reject_proposal(
agent: SolanaAgentKit,
transactionIndex?: number | bigint,
): Promise<string> {

View File

@@ -23,7 +23,7 @@ const { Multisig } = multisig.accounts;
* @param mint - Optional mint address for SPL tokens.
* @returns Transaction signature.
*/
export async function transfer_from_multisig(
export async function multisig_transfer_from_treasury(
agent: SolanaAgentKit,
amount: number,
to: PublicKey,

View File

@@ -0,0 +1 @@
export * from "./tensor_trade";

View File

@@ -1,4 +1,4 @@
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
import { TensorSwapSDK } from "@tensor-oss/tensorswap-sdk";
import { PublicKey, Transaction } from "@solana/web3.js";
import { AnchorProvider, Wallet } from "@coral-xyz/anchor";

View File

@@ -13,7 +13,7 @@ import {
getMint,
createAssociatedTokenAccountInstruction,
} from "@solana/spl-token";
import { SolanaAgentKit } from "../index";
import { SolanaAgentKit } from "../../index";
const MINIMUM_SOL_BALANCE = 0.003 * LAMPORTS_PER_SOL;

View File

@@ -0,0 +1 @@
export * from "./create_tiplinks";