Skip to content
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
66 changes: 66 additions & 0 deletions packages/plugin-defi/src/fluxbeam/actions/swap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { PublicKey } from "@solana/web3.js";
import { Action, SolanaAgentKit } from "solana-agent-kit";
import { z } from "zod";
import { fluxbeamSwap } from "../tools/swap";

const fluxbeamSwapAction: Action = {
name: "FLUXBEAM_SWAP_ACTION",
similes: [
"swap tokens on fluxbeam",
"exchange tokens on fluxbeam",
"trade tokens on fluxbeam",
"fluxbeam swap",
"buy token on fluxbeam",
"sell token on fluxbeam",
],
description: `Swap tokens using FluxBeam DEX.
Specify the input token, output token, amount, and optional slippage.`,
examples: [
[
{
input: {
outputMint: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", // BONK
amount: 1,
inputMint: "So11111111111111111111111111111111111111112", // SOL
},
output: {
status: "success",
message: "Swap completed successfully on FluxBeam",
transaction: "5KvgJ5vVZxUxefDGqzqkVLHzHxVTyYH9StYyHKgvHYmXJgqJKxEqy9k4Rz9LpXrHF9kUZB7",
},
explanation: "Swap 1 SOL for BONK on FluxBeam",
},
],
],
schema: z.object({
outputMint: z.string().describe("Target token mint address"),
amount: z.number().positive().describe("Amount of input token to swap"),
inputMint: z.string().optional().describe("Source token mint address (defaults to SOL)"),
slippageBps: z.number().optional().describe("Slippage tolerance in basis points (default: 50 = 0.5%)"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const txSignature = await fluxbeamSwap(
agent,
new PublicKey(input.outputMint),
input.amount,
input.inputMint ? new PublicKey(input.inputMint) : undefined,
input.slippageBps,
);

return {
status: "success",
message: "Swap completed successfully on FluxBeam",
transaction: txSignature,
};
} catch (error: any) {
return {
status: "error",
message: `FluxBeam swap failed: ${error.message}`,
error: error.message,
};
}
},
};

export default fluxbeamSwapAction;
71 changes: 71 additions & 0 deletions packages/plugin-defi/src/fluxbeam/tools/swap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { type PublicKey, VersionedTransaction } from "@solana/web3.js";
import { type SolanaAgentKit, signOrSendTX } from "solana-agent-kit";
import { FLUXBEAM_BASE_URI, TOKENS } from "../constants";
import { getTokenDecimals } from "../utils";

/**
* Swap tokens using FluxBeam
* @param agent SolanaAgentKit instance
* @param outputMint Target token mint address
* @param amount Amount to swap (in source token decimals)
* @param inputMint Source token mint address (defaults to SOL)
* @param slippageBps Slippage tolerance in basis points (default: 50 = 0.5%)
* @returns Transaction signature
*/
export async function fluxbeamSwap(
agent: SolanaAgentKit,
outputMint: PublicKey,
amount: number,
inputMint: PublicKey = TOKENS.SOL,
slippageBps: number = 50,
) {
try {
const isInputSol = inputMint.equals(TOKENS.SOL);
const inputDecimals = isInputSol
? 9
: await getTokenDecimals(agent, inputMint);

const scaledAmount = Math.floor(amount * Math.pow(10, inputDecimals));

// 1. Get Quote
const quoteResponse = await fetch(
`${FLUXBEAM_BASE_URI}/quote?inputMint=${inputMint.toBase58()}&outputMint=${outputMint.toBase58()}&amount=${scaledAmount}&slippageBps=${slippageBps}`,
);
const quote = await quoteResponse.json();

if (quote.error) {
throw new Error(`FluxBeam Quote Error: ${quote.error}`);
}

// 2. Get Swap Transaction
const swapResponse = await fetch(`${FLUXBEAM_BASE_URI}/swap/transaction`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
quote,
userPublicKey: agent.wallet.publicKey.toBase58(),
wrapAndUnwrapSol: true,
}),
});

const swapResult = await swapResponse.json();

if (swapResult.error) {
throw new Error(`FluxBeam Swap Error: ${swapResult.error}`);
}

// 3. Deserialize and Sign
const transactionBuf = Buffer.from(swapResult.transaction, "base64");
const transaction = VersionedTransaction.deserialize(transactionBuf);

// Update blockhash
const { blockhash } = await agent.connection.getLatestBlockhash();
transaction.message.recentBlockhash = blockhash;

return await signOrSendTX(agent, transaction);
} catch (error: any) {
throw new Error(`FluxBeam swap failed: ${error.message}`);
}
}
4 changes: 4 additions & 0 deletions packages/plugin-defi/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ import {

// Import Fluxbeam tools & actions
import fluxbeamCreatePoolAction from "./fluxbeam/actions/createPool";
import fluxbeamSwapAction from "./fluxbeam/actions/swap";
import { fluxBeamCreatePool } from "./fluxbeam/tools/create_pool";
import { fluxbeamSwap } from "./fluxbeam/tools/swap";

// Import Meteora actions & tools
import createMeteoraDLMMPoolAction from "./meteora/actions/createMeteoraDLMMPool";
Expand Down Expand Up @@ -321,6 +323,7 @@ const DefiPlugin = {

// Fluxbeam methods
fluxBeamCreatePool,
fluxbeamSwap,

// Sanctum methods
sanctumSwapLST,
Expand Down Expand Up @@ -426,6 +429,7 @@ const DefiPlugin = {

// Fluxbeam actions
fluxbeamCreatePoolAction,
fluxbeamSwapAction,

// Sanctum actions
sanctumAddLiquidityAction,
Expand Down
46 changes: 46 additions & 0 deletions packages/plugin-governance/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "@solana-agent-kit/plugin-governance",
"version": "2.0.0",
"type": "module",
"publishConfig": {
"access": "public"
},
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"scripts": {
"clean": "rm -rf dist .turbo node_modules",
"build": "tsup src/index.ts --clean --format cjs,esm --out-dir dist",
"test": "jest"
},
"repository": {
"type": "git",
"url": "https://github.com/sendaifun/solana-agent-kit.git"
},
"dependencies": {
"@solana/spl-governance": "^0.3.26",
"@solana/spl-token": "^0.4.9",
"bs58": "^6.0.0",
"solana-agent-kit": "workspace:*",
"zod": "^3.24.1"
},
"peerDependencies": {
"@solana/web3.js": "^1.98.2",
"solana-agent-kit": "2.0.7"
}
}
74 changes: 74 additions & 0 deletions packages/plugin-governance/src/actions/create_proposal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { PublicKey } from "@solana/web3.js";
import { Action, SolanaAgentKit } from "solana-agent-kit";
import { z } from "zod";
import { governanceCreateProposal } from "../tools/create_proposal";

const governanceCreateProposalAction: Action = {
name: "GOVERNANCE_CREATE_PROPOSAL_ACTION",
similes: [
"create a new proposal",
"start a proposal",
"initialize a proposal in realms",
"spl governance create proposal",
"realms proposal",
],
description: `Create a new Proposal in SPL Governance (Realms).
Specify the program ID, realm, governance, token owner record, name, and description link.`,
examples: [
[
{
input: {
programId: "GovER5Lthv3pLBZVvH7y3XmsabB3dB9K6P5xS8Xv",
realm: "8eN7m1K1WpT9U3Z8Xy8Z4Z5C6G7H8J9K0L1M2N3O4P5Q",
governance: "9rA8m1K1WpT9U3Z8Xy8Z4Z5C6G7H8J9K0L1M2N3O4P5Q",
tokenOwnerRecord: "6xY8m1K1WpT9U3Z8Xy8Z4Z5C6G7H8J9K0L1M2N3O4P5Q",
name: "Increase Fee to 1%",
descriptionLink: "https://example.com/proposal",
},
output: {
status: "success",
message: "Proposal created successfully",
transaction: "5KvgJ5vVZxUxefDGqzqkVLHzHxVTyYH9StYyHKgvHYmXJgqJKxEqy9k4Rz9LpXrHF9kUZB7",
},
explanation: "Create a new proposal in Realms to 'Increase Fee to 1%'",
},
],
],
schema: z.object({
programId: z.string().describe("SPL Governance program ID"),
realm: z.string().describe("Realm public key"),
governance: z.string().describe("Governance public key"),
tokenOwnerRecord: z.string().describe("Token owner record public key"),
name: z.string().describe("Name of the proposal"),
descriptionLink: z.string().url().describe("Link to the proposal description"),
governingTokenMint: z.string().optional().describe("Governing token mint (default to SOL)"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const txSignature = await governanceCreateProposal(
agent,
new PublicKey(input.programId),
new PublicKey(input.realm),
new PublicKey(input.governance),
new PublicKey(input.tokenOwnerRecord),
input.name,
input.descriptionLink,
input.governingTokenMint ? new PublicKey(input.governingTokenMint) : undefined,
);

return {
status: "success",
message: "Proposal created successfully",
transaction: txSignature,
};
} catch (error: any) {
return {
status: "error",
message: `Governance create proposal failed: ${error.message}`,
error: error.message,
};
}
},
};

export default governanceCreateProposalAction;
63 changes: 63 additions & 0 deletions packages/plugin-governance/src/actions/create_realm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { PublicKey } from "@solana/web3.js";
import { Action, SolanaAgentKit } from "solana-agent-kit";
import { z } from "zod";
import { governanceCreateRealm } from "../tools/create_realm";

const governanceCreateRealmAction: Action = {
name: "GOVERNANCE_CREATE_REALM_ACTION",
similes: [
"create a new realm",
"start a dao on realms",
"initialize a realm",
"spl governance create realm",
"realms setup",
],
description: `Create a new Realm in SPL Governance (Realms).
Specify the program ID, name of the realm, and community mint.`,
examples: [
[
{
input: {
programId: "GovER5Lthv3pLBZVvH7y3XmsabB3dB9K6P5xS8Xv",
name: "My Awesome DAO",
communityMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC
},
output: {
status: "success",
message: "Realm created successfully",
transaction: "5KvgJ5vVZxUxefDGqzqkVLHzHxVTyYH9StYyHKgvHYmXJgqJKxEqy9k4Rz9LpXrHF9kUZB7",
},
explanation: "Create a new DAO realm named 'My Awesome DAO' using USDC as community mint",
},
],
],
schema: z.object({
programId: z.string().describe("SPL Governance program ID"),
name: z.string().describe("Name of the realm"),
communityMint: z.string().describe("Community token mint address"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const txSignature = await governanceCreateRealm(
agent,
new PublicKey(input.programId),
input.name,
new PublicKey(input.communityMint),
);

return {
status: "success",
message: "Realm created successfully",
transaction: txSignature,
};
} catch (error: any) {
return {
status: "error",
message: `Governance create realm failed: ${error.message}`,
error: error.message,
};
}
},
};

export default governanceCreateRealmAction;
Loading