Skip to content

Commit 0bc7ed9

Browse files
authored
Merge branch 'develop' into fix-multi-biome-06
2 parents c5ddde3 + 085e970 commit 0bc7ed9

31 files changed

+2638
-262
lines changed

.env.example

+3
Original file line numberDiff line numberDiff line change
@@ -952,4 +952,7 @@ ARBITRAGE_EVM_PRIVATE_KEY= # Private key for the wallet executi
952952
FLASHBOTS_RELAY_SIGNING_KEY= # Signing key for Flashbots relay interactions
953953
BUNDLE_EXECUTOR_ADDRESS= # Address of the bundle executor contract
954954

955+
# DESK Exchange Plugin Configration
956+
DESK_EXCHANGE_PRIVATE_KEY= # Required for trading and cancelling orders
957+
DESK_EXCHANGE_NETWORK= # "mainnet" or "testnet
955958

agent/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@
5555
"@elizaos/plugin-coinmarketcap": "workspace:*",
5656
"@elizaos/plugin-conflux": "workspace:*",
5757
"@elizaos/plugin-cosmos": "workspace:*",
58+
"@elizaos/plugin-desk-exchange": "workspace:*",
5859
"@elizaos/plugin-echochambers": "workspace:*",
5960
"@elizaos/plugin-evm": "workspace:*",
61+
"@elizaos/plugin-edwin": "workspace:*",
6062
"@elizaos/plugin-flow": "workspace:*",
6163
"@elizaos/plugin-gelato": "workspace:*",
6264
"@elizaos/plugin-giphy": "workspace:*",

agent/src/index.ts

+10
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ import { coinmarketcapPlugin } from "@elizaos/plugin-coinmarketcap";
8484
import { confluxPlugin } from "@elizaos/plugin-conflux";
8585
import { createCosmosPlugin } from "@elizaos/plugin-cosmos";
8686
import { cronosZkEVMPlugin } from "@elizaos/plugin-cronoszkevm";
87+
import { deskExchangePlugin } from "@elizaos/plugin-desk-exchange";
8788
import { evmPlugin } from "@elizaos/plugin-evm";
89+
import { edwinPlugin } from "@elizaos/plugin-edwin";
8890
import { flowPlugin } from "@elizaos/plugin-flow";
8991
import { fuelPlugin } from "@elizaos/plugin-fuel";
9092
import { genLayerPlugin } from "@elizaos/plugin-genlayer";
@@ -1067,6 +1069,10 @@ export async function createAgent(
10671069
getSecret(character, "WALLET_PUBLIC_KEY")?.startsWith("0x"))
10681070
? evmPlugin
10691071
: null,
1072+
(getSecret(character, "EVM_PRIVATE_KEY") ||
1073+
getSecret(character, "SOLANA_PRIVATE_KEY"))
1074+
? edwinPlugin
1075+
: null,
10701076
(getSecret(character, "EVM_PUBLIC_KEY") ||
10711077
getSecret(character, "INJECTIVE_PUBLIC_KEY")) &&
10721078
getSecret(character, "INJECTIVE_PRIVATE_KEY")
@@ -1295,6 +1301,10 @@ export async function createAgent(
12951301
getSecret(character, "ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS")
12961302
? arbitragePlugin
12971303
: null,
1304+
getSecret(character, "DESK_EXCHANGE_PRIVATE_KEY") ||
1305+
getSecret(character, "DESK_EXCHANGE_NETWORK")
1306+
? deskExchangePlugin
1307+
: null,
12981308
]
12991309
.flat()
13001310
.filter(Boolean),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
import {
2+
type ActionExample,
3+
composeContext,
4+
type Content,
5+
elizaLogger,
6+
generateObject,
7+
type HandlerCallback,
8+
type IAgentRuntime,
9+
type Memory,
10+
ModelClass,
11+
type State,
12+
type Action,
13+
} from "@elizaos/core";
14+
import axios from "axios";
15+
import { z } from "zod";
16+
import { getApiConfig, validateCoingeckoConfig } from "../environment";
17+
import { getNetworkNewPoolsTemplate } from "../templates/networkNewPools";
18+
import { getNetworksData } from "../providers/networkProvider";
19+
20+
interface NewPool {
21+
id: string;
22+
type: string;
23+
attributes: {
24+
name: string;
25+
market_cap_usd: string;
26+
fdv_usd: string;
27+
reserve_in_usd: string;
28+
pool_created_at: string;
29+
};
30+
}
31+
32+
interface NewPoolsResponse {
33+
data: NewPool[];
34+
}
35+
36+
export const GetNetworkNewPoolsSchema = z.object({
37+
networkId: z.string(),
38+
limit: z.number().min(1).max(100).default(10),
39+
});
40+
41+
export type GetNetworkNewPoolsContent = z.infer<
42+
typeof GetNetworkNewPoolsSchema
43+
> &
44+
Content;
45+
46+
export const isGetNetworkNewPoolsContent = (
47+
obj: unknown
48+
): obj is GetNetworkNewPoolsContent => {
49+
return GetNetworkNewPoolsSchema.safeParse(obj).success;
50+
};
51+
52+
export default {
53+
name: "GET_NETWORK_NEW_POOLS",
54+
similes: [
55+
"NETWORK_NEW_POOLS",
56+
"CHAIN_NEW_POOLS",
57+
"NEW_POOLS_BY_NETWORK",
58+
"RECENT_POOLS",
59+
"LATEST_POOLS",
60+
],
61+
validate: async (runtime: IAgentRuntime, _message: Memory) => {
62+
await validateCoingeckoConfig(runtime);
63+
return true;
64+
},
65+
description:
66+
"Get list of newly created pools for a specific network from CoinGecko's onchain data",
67+
handler: async (
68+
runtime: IAgentRuntime,
69+
message: Memory,
70+
state: State,
71+
_options: { [key: string]: unknown },
72+
callback?: HandlerCallback
73+
): Promise<boolean> => {
74+
elizaLogger.log("Starting CoinGecko GET_NETWORK_NEW_POOLS handler...");
75+
76+
let currentState = state;
77+
if (!currentState) {
78+
currentState = (await runtime.composeState(message)) as State;
79+
} else {
80+
currentState = await runtime.updateRecentMessageState(currentState);
81+
}
82+
83+
try {
84+
elizaLogger.log("Composing network new pools context...");
85+
const newPoolsContext = composeContext({
86+
state: currentState,
87+
template: getNetworkNewPoolsTemplate,
88+
});
89+
90+
const result = await generateObject({
91+
runtime,
92+
context: newPoolsContext,
93+
modelClass: ModelClass.LARGE,
94+
schema: GetNetworkNewPoolsSchema,
95+
});
96+
97+
if (!isGetNetworkNewPoolsContent(result.object)) {
98+
elizaLogger.error("Invalid network new pools request format");
99+
return false;
100+
}
101+
102+
// Fetch networks data first
103+
const networks = await getNetworksData(runtime);
104+
105+
// Fetch networks data first
106+
const networksResponse = await getNetworksData(runtime);
107+
108+
// Find the matching network from the data array
109+
const network = networksResponse.find((n) => {
110+
const searchTerm = (
111+
result.object as { networkId: string }
112+
).networkId.toLowerCase();
113+
return (
114+
n.id.toLowerCase() === searchTerm ||
115+
n.attributes.name.toLowerCase().includes(searchTerm) ||
116+
n.attributes.coingecko_asset_platform_id.toLowerCase() ===
117+
searchTerm
118+
);
119+
});
120+
121+
if (!network) {
122+
throw new Error(
123+
`Network ${result.object.networkId} not found in available networks`
124+
);
125+
}
126+
127+
const config = await validateCoingeckoConfig(runtime);
128+
const { baseUrl, apiKey, headerKey } = getApiConfig(config);
129+
130+
elizaLogger.log(
131+
`Fetching new pools data for network: ${network.id}`
132+
);
133+
134+
const response = await axios.get<NewPoolsResponse>(
135+
`${baseUrl}/onchain/networks/${network.id}/new_pools?include=base_token,dex`,
136+
{
137+
headers: {
138+
[headerKey]: apiKey,
139+
},
140+
}
141+
);
142+
143+
if (!response.data) {
144+
throw new Error("No data received from CoinGecko API");
145+
}
146+
147+
const formattedData = response.data.data
148+
.slice(0, result.object.limit)
149+
.map((pool) => ({
150+
name: pool.attributes.name,
151+
marketCap: Number(
152+
pool.attributes.market_cap_usd
153+
).toLocaleString("en-US", {
154+
style: "currency",
155+
currency: "USD",
156+
}),
157+
fdv: Number(pool.attributes.fdv_usd).toLocaleString(
158+
"en-US",
159+
{
160+
style: "currency",
161+
currency: "USD",
162+
}
163+
),
164+
reserveUSD: Number(
165+
pool.attributes.reserve_in_usd
166+
).toLocaleString("en-US", {
167+
style: "currency",
168+
currency: "USD",
169+
}),
170+
createdAt: new Date(
171+
pool.attributes.pool_created_at
172+
).toLocaleDateString(),
173+
}));
174+
175+
const responseText = [
176+
`New Pools Overview for ${network.attributes.name}:`,
177+
"",
178+
...formattedData.map((pool, index) =>
179+
[
180+
`${index + 1}. ${pool.name}`,
181+
` Market Cap: ${pool.marketCap}`,
182+
` FDV: ${pool.fdv}`,
183+
` Reserve: ${pool.reserveUSD}`,
184+
` Created: ${pool.createdAt}`,
185+
"",
186+
].join("\n")
187+
),
188+
].join("\n");
189+
190+
elizaLogger.success(
191+
"Network new pools data retrieved successfully!"
192+
);
193+
194+
if (callback) {
195+
callback({
196+
text: responseText,
197+
content: {
198+
networkId: network.id,
199+
networkName: network.attributes.name,
200+
newPools: formattedData,
201+
timestamp: new Date().toISOString(),
202+
},
203+
});
204+
}
205+
206+
return true;
207+
} catch (error) {
208+
elizaLogger.error("Error in GET_NETWORK_NEW_POOLS handler:", error);
209+
210+
const errorMessage =
211+
error.response?.status === 429
212+
? "Rate limit exceeded. Please try again later."
213+
: `Error fetching new pools data: ${error.message}`;
214+
215+
if (callback) {
216+
callback({
217+
text: errorMessage,
218+
content: {
219+
error: error.message,
220+
statusCode: error.response?.status,
221+
},
222+
});
223+
}
224+
return false;
225+
}
226+
},
227+
228+
examples: [
229+
[
230+
{
231+
user: "{{user1}}",
232+
content: {
233+
text: "Show me new liquidity pools on Ethereum",
234+
},
235+
},
236+
{
237+
user: "{{agent}}",
238+
content: {
239+
text: "I'll check the new Ethereum liquidity pools for you.",
240+
action: "GET_NETWORK_NEW_POOLS",
241+
},
242+
},
243+
{
244+
user: "{{agent}}",
245+
content: {
246+
text: "Here are the new pools on ETHEREUM:\n1. PEPE / WETH\n Market Cap: $954,636,707\n FDV: $6,402,478,508\n Reserve: $363,641,037\n Created: 1/19/2025\n2. SUSHI / WETH\n Market Cap: $8,844,297,825\n FDV: $43,874,068,484\n Reserve: $718,413,745\n Created: 1/17/2025",
247+
},
248+
},
249+
],
250+
[
251+
{
252+
user: "{{user1}}",
253+
content: {
254+
text: "What are the 5 latest pools on BSC?",
255+
},
256+
},
257+
{
258+
user: "{{agent}}",
259+
content: {
260+
text: "I'll fetch the 5 latest pools on BSC for you.",
261+
action: "GET_NETWORK_NEW_POOLS",
262+
},
263+
},
264+
{
265+
user: "{{agent}}",
266+
content: {
267+
text: "Here are the 5 newest pools on BSC:\n1. CAKE / WBNB\n Market Cap: $954,636,707\n FDV: $6,402,478,508\n Reserve: $363,641,037\n Created: 1/19/2025",
268+
},
269+
},
270+
],
271+
[
272+
{
273+
user: "{{user1}}",
274+
content: {
275+
text: "List all recent pools on Polygon",
276+
},
277+
},
278+
{
279+
user: "{{agent}}",
280+
content: {
281+
text: "I'll get all the recently added pools on Polygon for you.",
282+
action: "GET_NETWORK_NEW_POOLS",
283+
},
284+
},
285+
{
286+
user: "{{agent}}",
287+
content: {
288+
text: "Here are all new pools on POLYGON:\n1. MATIC / USDC\n Market Cap: $954,636,707\n FDV: $6,402,478,508\n Reserve: $363,641,037\n Created: 1/19/2025",
289+
},
290+
},
291+
],
292+
] as ActionExample[][],
293+
} as Action;

0 commit comments

Comments
 (0)