Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Fluxbeam Features #148

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions src/actions/fluxbeam/fluxbeamCreatePool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { PublicKey } from "@solana/web3.js";
import { Action } from "../../types/action";
import { SolanaAgentKit } from "../../agent";
import { z } from "zod";
import { createPoolFluxBeam } from "../../tools";

const fluxbeamCreatePoolAction: Action = {
name: "FLUXBEAM_CREATE_POOL",
similes: [
"create liquidity pool on fluxbeam",
"add new pool to fluxbeam",
"initialize fluxbeam pool",
"setup trading pair on fluxbeam",
"create token pair pool",
],
description: `This tool allows you to create a new liquidity pool on FluxBeam DEX with two tokens.`,
examples: [
[
{
input: {
token_a: "So11111111111111111111111111111111111111112",
token_a_amount: 1,
token_b: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
token_b_amount: 1000,
},
output: {
status: "success",
message: "Pool created successfully on FluxBeam",
transaction:
"4KvgJ5vVZxUxefDGqzqkVLHzHxVTyYH9StYyHKgvHYmXJgqJKxEqy9k4Rz9LpXrHF9kUZB7",
token_a: "SOL",
token_a_amount: 1,
token_b: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
token_b_amount: 1000,
},
explanation: "Create a new SOL-USDC pool with 1 SOL and 1000 USDC",
},
],
[
{
input: {
token_a: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
token_a_amount: 1000,
token_b: "7i5KKsX2weiTkry7jA4ZwSuXGhs5eJBEjY8vVxR4pfRx",
token_b_amount: 1000,
},
output: {
status: "success",
message: "Pool created successfully on FluxBeam",
transaction:
"5UfgJ5vVZxUxefDGqzqkVLHzHxVTyYH9StYyHKgvHYmXJgqJKxEqy9k4Rz9LpXrHF9kUZB7",
token_a: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
token_a_amount: 1000,
token_b: "7i5KKsX2weiTkry7jA4ZwSuXGhs5eJBEjY8vVxR4pfRx",
token_b_amount: 1000,
},
explanation: "Create a new USDC-USDT pool with 1000 USDC and 1000 USDT",
},
],
],
schema: z.object({
token_a: z.string().min(32, "Invalid token_a mint address"),
token_a_amount: z.number().positive("Token A amount must be positive"),
token_b: z.string().min(32, "Invalid token_b mint address"),
token_b_amount: z.number().positive("Token B amount must be positive"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const tx = await createPoolFluxBeam(
agent,
new PublicKey(input.token_a),
input.token_a_amount,
new PublicKey(input.token_b),
input.token_b_amount,
);

return {
status: "success",
message: "Pool created successfully on FluxBeam",
transaction: tx,
token_a: input.token_a,
token_a_amount: input.token_a_amount,
token_b: input.token_b,
token_b_amount: input.token_b_amount,
};
} catch (error: any) {
return {
status: "error",
message: `FluxBeam pool creation failed: ${error.message}`,
error: error.message,
};
}
},
};

export default fluxbeamCreatePoolAction;
117 changes: 117 additions & 0 deletions src/actions/fluxbeam/fluxbeamSwapAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { PublicKey } from "@solana/web3.js";
import { Action } from "../../types/action";
import { SolanaAgentKit } from "../../agent";
import { z } from "zod";
import { swapFluxBeam } from "../../tools";

const fluxbeamSwapAction: Action = {
name: "FLUXBEAM_SWAP",
similes: [
"swap tokens on fluxbeam",
"exchange tokens using fluxbeam",
"trade on fluxbeam",
"convert tokens via fluxbeam",
"use fluxbeam dex",
],
description: `This tool allows you to swap tokens using the FluxBeam DEX on Solana.`,
examples: [
[
{
input: {
outputMint: "So11111111111111111111111111111111111111112",
inputAmount: 100,
inputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
},
output: {
status: "success",
message: "Swap executed successfully on FluxBeam",
transactionSignature:
"3KvgJ5vVZxUxefDGqzqkVLHzHxVTyYH9StYyHKgvHYmXJgqJKxEqy9k4Rz9LpXrHF9kUZB7",
inputAmount: 100,
inputToken: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
outputToken: "So11111111111111111111111111111111111111112",
},
explanation: "Swap 100 USDC for SOL using FluxBeam DEX",
},
],
[
{
input: {
outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
inputAmount: 1,
slippageBps: 100,
},
output: {
status: "success",
message: "Swap executed successfully on FluxBeam",
transactionSignature:
"2UfgJ5vVZxUxefDGqzqkVLHzHxVTyYH9StYyHKgvHYmXJgqJKxEqy9k4Rz9LpXrHF9kUZB7",
inputAmount: 1,
inputToken: "SOL",
outputToken: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
},
explanation: "Swap 1 SOL for USDC with 1% slippage on FluxBeam",
},
],
],
schema: z.object({
outputMint: z
.string()
.min(32, "Invalid output mint address")
.describe("The token mint address you want to receive"),
inputAmount: z
.number()
.positive("Input amount must be positive")
.describe("The amount of tokens to swap"),
inputMint: z
.string()
.min(32, "Invalid input mint address")
.optional()
.describe(
"The token mint address you want to swap from (default is SOL)",
),
slippageBps: z
.number()
.min(0)
.max(10000)
.optional()
.describe("Slippage tolerance in basis points (default: 0)"),
}),
handler: async (
solanaAgent: SolanaAgentKit,
swapParams: Record<string, any>,
) => {
try {
// Extract parameters with optional defaults
const { outputMint, inputAmount, inputMint, slippageBps } = swapParams;

// Execute the token swap on FluxBeam DEX
const transactionSignature = await swapFluxBeam(
solanaAgent,
new PublicKey(outputMint),
inputAmount,
inputMint ? new PublicKey(inputMint) : undefined, // Default to SOL if inputMint is not provided
slippageBps,
);

// Return success response
return {
status: "success",
message: "Swap executed successfully on FluxBeam",
transactionSignature,
inputAmount,
inputToken: inputMint || "SOL", // Default to "SOL" if inputMint is not provided
outputToken: outputMint,
};
} catch (error: any) {
// Handle error and return a detailed response
return {
status: "error",
message: `FluxBeam swap failed: ${error.message}`,
error: error.message,
};
}
},
};

export default fluxbeamSwapAction;
4 changes: 4 additions & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import launchPumpfunTokenAction from "./pumpfun/launchPumpfunToken";
import getWalletAddressAction from "./agent/getWalletAddress";
import flashOpenTradeAction from "./flash/flashOpenTrade";
import flashCloseTradeAction from "./flash/flashCloseTrade";
import fluxbeamCreatePoolAction from "./fluxbeam/fluxbeamCreatePool";
import fluxbeamSwapAction from "./fluxbeam/fluxbeamSwapAction";
import createMultisigAction from "./squads/createMultisig";
import approveMultisigProposalAction from "./squads/approveMultisigProposal";
import createMultisigProposalAction from "./squads/createMultisigProposal";
Expand Down Expand Up @@ -113,6 +115,8 @@ export const ACTIONS = {
CREATE_ORCA_SINGLE_SIDED_WHIRLPOOL_ACTION:
createOrcaSingleSidedWhirlpoolAction,
LAUNCH_PUMPFUN_TOKEN_ACTION: launchPumpfunTokenAction,
FLUXBEAM_CREATE_POOL_ACTION: fluxbeamCreatePoolAction,
FLUXBEAM_SWAP_ACTION: fluxbeamSwapAction,
FLASH_OPEN_TRADE_ACTION: flashOpenTradeAction,
FLASH_CLOSE_TRADE_ACTION: flashCloseTradeAction,
CREATE_MULTISIG_ACTION: createMultisigAction,
Expand Down
25 changes: 25 additions & 0 deletions src/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ import {
fetchTokenDetailedReport,
fetchPythPrice,
fetchPythPriceFeedID,
swapFluxBeam,
createPoolFluxBeam,
flashOpenTrade,
flashCloseTrade,
createMeteoraDynamicAMMPool,
Expand Down Expand Up @@ -691,6 +693,29 @@ export class SolanaAgentKit {
return fetchTokenDetailedReport(mint);
}

async swapFluxBeam(
outputMint: PublicKey,
inputAmount: number,
inputMint?: PublicKey,
slippageBps: number = DEFAULT_OPTIONS.SLIPPAGE_BPS,
): Promise<string> {
return swapFluxBeam(this, outputMint, inputAmount, inputMint, slippageBps);
}

async createPoolFluxBeam(
token_a: PublicKey,
token_a_amount: number,
token_b: PublicKey,
token_b_amount: number,
): Promise<string> {
return createPoolFluxBeam(
this,
token_a,
token_a_amount,
token_b,
token_b_amount,
);
}
/**
* Opens a new trading position on Flash.Trade
* @param params Flash trade parameters including market, side, collateral, leverage, and pool name
Expand Down
50 changes: 50 additions & 0 deletions src/langchain/fluxbeam/create_pool_fluxbeam.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { PublicKey } from "@solana/web3.js";
import { SolanaAgentKit } from "../../agent";
import { Tool } from "langchain/tools";

export class SolanaCreatePoolFluxBeamTool extends Tool {
name = "solana_create_pool_fluxbeam";
description = `This tool can be used to create a new liquidity pool using FluxBeam.
Inputs ( input is a JSON string ):
tokenA: string, eg "So11111111111111111111111111111111111111112" (required)
tokenAAmount: number, eg 100 (required)
tokenB: string, eg "SENDdRQtYMWaQrBroBrJ2Q53fgVuq95CV9UPGEvpCxa" (required)
tokenBAmount: number, eg 200 (required)`;

constructor(private solanaAgent: SolanaAgentKit) {
super();
}

protected async _call(input: string): Promise<string> {
try {
const parsedInput = JSON.parse(input);
const tokenA = new PublicKey(parsedInput.tokenA);
const tokenAAmount = parsedInput.tokenAAmount;
const tokenB = new PublicKey(parsedInput.tokenB);
const tokenBAmount = parsedInput.tokenBAmount;

const signature = await this.solanaAgent.createPoolFluxBeam(
tokenA,
tokenAAmount,
tokenB,
tokenBAmount,
);

return JSON.stringify({
status: "success",
message: "Pool created successfully",
transaction: signature,
tokenA: parsedInput.tokenA,
tokenAAmount: parsedInput.tokenAAmount,
tokenB: parsedInput.tokenB,
tokenBAmount: parsedInput.tokenBAmount,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
2 changes: 2 additions & 0 deletions src/langchain/fluxbeam/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./swap_fluxbeam";
export * from "./create_pool_fluxbeam";
58 changes: 58 additions & 0 deletions src/langchain/fluxbeam/swap_fluxbeam.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { PublicKey } from "@solana/web3.js";
import { SolanaAgentKit } from "../../agent";
import { Tool } from "langchain/tools";

export class SolanaSwapFluxBeamTool extends Tool {
name = "solana_swap_fluxbeam";
description = `This tool can be used to swap tokens using FluxBeam DEX.
Inputs (input is a JSON string):
- outputMint (string): eg "So11111111111111111111111111111111111111112" (required)
- inputAmount (number): eg 1 or 0.01 (required)
- inputMint (string): eg "USDC" or "So11111111111111111111111111111111111111112" (optional)
- slippageBps (number): eg 300 for 3% (optional)`;

constructor(private solanaAgent: SolanaAgentKit) {
super();
}

protected async _call(input: string): Promise<string> {
try {
// Parse the JSON input
const parsedInput = JSON.parse(input);
const { outputMint, inputAmount, inputMint, slippageBps } = parsedInput;

if (!outputMint || !inputAmount) {
throw new Error(
"Required parameters 'outputMint' and 'inputAmount' are missing.",
);
}

// Perform the token swap using the SolanaAgentKit instance
const transactionSignature = await this.solanaAgent.swapFluxBeam(
new PublicKey(outputMint),
inputAmount,
inputMint
? new PublicKey(inputMint)
: new PublicKey("So11111111111111111111111111111111111111112"), // Default to SOL
slippageBps,
);

// Return success response
return JSON.stringify({
status: "success",
message: "Swap executed successfully",
transaction: transactionSignature,
inputAmount,
inputToken: inputMint || "USDC",
outputToken: outputMint,
});
} catch (error: any) {
// Return error response
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
Loading