Skip to content

Commit 1bbb6ca

Browse files
author
Freytes
committed
wip: Added meteora, raydium pools
1 parent 0818597 commit 1bbb6ca

File tree

9 files changed

+967
-3
lines changed

9 files changed

+967
-3
lines changed

packages/agent/src/swarm/investmentManager/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ dotenv.config({ path: "../../.env" });
1010
const character: Character = {
1111
name: "Spartan",
1212
plugins: [
13-
//"@elizaos/plugin-anthropic",
1413
"@elizaos/plugin-openai",
14+
"@elizaos/plugin-anthropic",
1515
"@elizaos/plugin-discord",
1616
"@elizaos/plugin-node",
1717
],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import {
2+
Action,
3+
elizaLogger,
4+
generateText,
5+
HandlerCallback,
6+
IAgentRuntime,
7+
Memory,
8+
ModelClass,
9+
parseJSONObjectFromText,
10+
settings,
11+
State,
12+
} from "@elizaos/core";
13+
import { PublicKey } from "@solana/web3.js";
14+
import { DLMM, StrategyType } from "@meteora-ag/dlmm";
15+
import { sendTransaction } from "../../utils/sendTransaction";
16+
import { loadWallet } from "../../utils/loadWallet";
17+
18+
interface FetchedPosition {
19+
poolAddress: string;
20+
positionPubKey: string;
21+
inRange: boolean;
22+
distanceFromActiveBinBps: number;
23+
binRange: number;
24+
}
25+
26+
interface ManagePositionsInput {
27+
repositionThresholdBps: number;
28+
intervalSeconds: number;
29+
slippageToleranceBps: number;
30+
}
31+
32+
export const managePositions: Action = {
33+
name: 'manage_meteora_positions',
34+
similes: ["AUTOMATE_METEORA_REBALANCING", "AUTOMATE_METEORA_POSITIONS"],
35+
description: "Automatically manage Meteora positions by rebalancing when they drift from active bin",
36+
37+
validate: async (runtime: IAgentRuntime, message: Memory): Promise<boolean> => {
38+
const config = await extractAndValidateConfiguration(message.content.text, runtime);
39+
return !!config;
40+
},
41+
42+
handler: async (
43+
runtime: IAgentRuntime,
44+
message: Memory,
45+
state: State,
46+
params: { [key: string]: unknown },
47+
callback?: HandlerCallback
48+
) => {
49+
elizaLogger.log("Start managing Meteora positions");
50+
51+
const { repositionThresholdBps, slippageToleranceBps }: ManagePositionsInput =
52+
await extractAndValidateConfiguration(message.content.text, runtime);
53+
54+
const fetchedPositions = await extractFetchedPositions(state.providers, runtime);
55+
const { signer: wallet } = await loadWallet(runtime, true);
56+
57+
await handleRepositioning(
58+
fetchedPositions,
59+
repositionThresholdBps,
60+
wallet
61+
);
62+
63+
return true;
64+
},
65+
examples: []
66+
};
67+
68+
async function handleRepositioning(
69+
fetchedPositions: FetchedPosition[],
70+
repositionThresholdBps: number,
71+
wallet: any
72+
) {
73+
return await Promise.all(
74+
fetchedPositions.map(async (position) => {
75+
if (position.distanceFromActiveBinBps > repositionThresholdBps) {
76+
const dlmmPool = await DLMM.create(
77+
wallet.connection,
78+
new PublicKey(position.poolAddress)
79+
);
80+
81+
const activeBin = await dlmmPool.getActiveBin();
82+
const TOTAL_RANGE_INTERVAL = position.binRange;
83+
84+
try {
85+
// Remove existing liquidity
86+
const { userPositions } = await dlmmPool.getPositionsByUserAndLbPair(wallet.publicKey);
87+
const userPosition = userPositions.find(p =>
88+
p.publicKey.toString() === position.positionPubKey
89+
);
90+
91+
if (!userPosition) return null;
92+
93+
const binIdsToRemove = userPosition.positionData.positionBinData.map(bin => bin.binId);
94+
const removeLiquidityTx = await dlmmPool.removeLiquidity({
95+
position: userPosition.publicKey,
96+
user: wallet.publicKey,
97+
binIds: binIdsToRemove,
98+
liquiditiesBpsToRemove: new Array(binIdsToRemove.length).fill(10000), // 100%
99+
shouldClaimAndClose: true
100+
});
101+
102+
await sendTransaction(wallet.connection, removeLiquidityTx, wallet);
103+
104+
// Create new position around active bin
105+
const minBinId = activeBin.binId - TOTAL_RANGE_INTERVAL;
106+
const maxBinId = activeBin.binId + TOTAL_RANGE_INTERVAL;
107+
108+
const newPosition = await dlmmPool.initializePositionAndAddLiquidityByStrategy({
109+
positionPubKey: userPosition.publicKey,
110+
user: wallet.publicKey,
111+
totalXAmount: userPosition.positionData.totalXAmount,
112+
totalYAmount: userPosition.positionData.totalYAmount,
113+
strategy: {
114+
maxBinId,
115+
minBinId,
116+
strategyType: StrategyType.SpotBalanced,
117+
},
118+
});
119+
120+
await sendTransaction(wallet.connection, newPosition, wallet);
121+
122+
return {
123+
oldPosition: position.positionPubKey,
124+
newPosition: userPosition.publicKey.toString()
125+
};
126+
127+
} catch (error) {
128+
elizaLogger.error(`Error repositioning: ${error}`);
129+
return null;
130+
}
131+
}
132+
return null;
133+
})
134+
);
135+
}
136+
137+
// ... rest of the helper functions similar to Orca implementation ...

0 commit comments

Comments
 (0)