Skip to content

Commit d88c1fa

Browse files
authored
Merge pull request elizaOS#1812 from Lukapetro/feature/add-binance-plugin
Feature/add binance plugin
2 parents 4c53ea2 + 1ae56a3 commit d88c1fa

27 files changed

+2116
-67
lines changed

agent/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"@elizaos/plugin-0g": "workspace:*",
3434
"@elizaos/plugin-abstract": "workspace:*",
3535
"@elizaos/plugin-aptos": "workspace:*",
36+
"@elizaos/plugin-binance": "workspace:*",
3637
"@elizaos/plugin-avail": "workspace:*",
3738
"@elizaos/plugin-bootstrap": "workspace:*",
3839
"@ai16z/plugin-cosmos": "workspace:*",
@@ -78,4 +79,4 @@
7879
"ts-node": "10.9.2",
7980
"tsup": "8.3.5"
8081
}
81-
}
82+
}

agent/src/index.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ import { zgPlugin } from "@elizaos/plugin-0g";
3333
import { bootstrapPlugin } from "@elizaos/plugin-bootstrap";
3434
import createGoatPlugin from "@elizaos/plugin-goat";
3535
// import { intifacePlugin } from "@elizaos/plugin-intiface";
36-
import { genLayerPlugin } from "@elizaos/plugin-genlayer";
3736
import { DirectClient } from "@elizaos/client-direct";
3837
import { ThreeDGenerationPlugin } from "@elizaos/plugin-3d-generation";
3938
import { abstractPlugin } from "@elizaos/plugin-abstract";
4039
import { aptosPlugin } from "@elizaos/plugin-aptos";
4140
import { avalanchePlugin } from "@elizaos/plugin-avalanche";
41+
import { binancePlugin } from "@elizaos/plugin-binance";
4242
import {
4343
advancedTradePlugin,
4444
coinbaseCommercePlugin,
@@ -53,6 +53,7 @@ import { echoChambersPlugin } from "@elizaos/plugin-echochambers";
5353
import { evmPlugin } from "@elizaos/plugin-evm";
5454
import { flowPlugin } from "@elizaos/plugin-flow";
5555
import { fuelPlugin } from "@elizaos/plugin-fuel";
56+
import { genLayerPlugin } from "@elizaos/plugin-genlayer";
5657
import { imageGenerationPlugin } from "@elizaos/plugin-image-generation";
5758
import { multiversxPlugin } from "@elizaos/plugin-multiversx";
5859
import { nearPlugin } from "@elizaos/plugin-near";
@@ -65,10 +66,11 @@ import { TEEMode, teePlugin } from "@elizaos/plugin-tee";
6566
import { teeMarlinPlugin } from "@elizaos/plugin-tee-marlin";
6667
import { tonPlugin } from "@elizaos/plugin-ton";
6768
import { webSearchPlugin } from "@elizaos/plugin-web-search";
68-
import { stargazePlugin } from "@elizaos/plugin-stargaze";
6969
import { zksyncEraPlugin } from "@elizaos/plugin-zksync-era";
70+
7071
import { availPlugin } from "@elizaos/plugin-avail";
7172
import { openWeatherPlugin } from "@elizaos/plugin-open-weather";
73+
import { stargazePlugin } from "@elizaos/plugin-stargaze";
7274
import Database from "better-sqlite3";
7375
import fs from "fs";
7476
import net from "net";
@@ -612,6 +614,10 @@ export async function createAgent(
612614
getSecret(character, "ABSTRACT_PRIVATE_KEY")
613615
? abstractPlugin
614616
: null,
617+
getSecret(character, "BINANCE_API_KEY") &&
618+
getSecret(character, "BINANCE_SECRET_KEY")
619+
? binancePlugin
620+
: null,
615621
getSecret(character, "FLOW_ADDRESS") &&
616622
getSecret(character, "FLOW_PRIVATE_KEY")
617623
? flowPlugin

packages/plugin-binance/README.md

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Binance Plugin for Eliza
2+
3+
This plugin enables Eliza to interact with the Binance cryptocurrency exchange, providing capabilities for checking prices, executing trades, and managing spot wallet balances.
4+
5+
## Features
6+
7+
- 📊 Real-time cryptocurrency price checks
8+
- 💱 Spot trading (market and limit orders)
9+
- 💰 Wallet balance inquiries
10+
- ✅ Comprehensive error handling
11+
- 🔒 Secure API integration
12+
13+
## Prerequisites
14+
15+
1. **Binance Account**: You need a Binance account to use this plugin
16+
2. **API Keys**: Generate API keys from your Binance account:
17+
- Go to your Binance account settings
18+
- Navigate to API Management
19+
- Create a new API key
20+
- Enable spot trading permissions
21+
- Store your API key and secret securely
22+
23+
## Configuration
24+
25+
Set the following environment variables:
26+
27+
```env
28+
BINANCE_API_KEY=your_api_key
29+
BINANCE_SECRET_KEY=your_secret_key
30+
```
31+
32+
## Installation
33+
34+
Add the plugin to your Eliza configuration:
35+
36+
```json
37+
{
38+
"plugins": ["@elizaos/plugin-binance"]
39+
}
40+
```
41+
42+
## Available Actions
43+
44+
The plugin provides the following actions:
45+
46+
1. **GET_PRICE**: Check cryptocurrency prices
47+
48+
- Example: "What's the current price of Bitcoin?"
49+
- Example: "Check ETH price in USDT"
50+
51+
2. **EXECUTE_SPOT_TRADE**: Execute spot trades
52+
53+
- Example: "Buy 0.1 BTC at market price"
54+
- Example: "Sell 100 USDT worth of ETH"
55+
56+
3. **GET_SPOT_BALANCE**: Check wallet balances
57+
- Example: "What's my BTC balance?"
58+
- Example: "Show all my wallet balances"
59+
60+
## Important Notes
61+
62+
1. **API Rate Limits**: Binance implements rate limiting:
63+
64+
- 1200 requests per minute for most endpoints
65+
- Some endpoints have specific weight limits
66+
- The plugin handles rate limiting errors appropriately
67+
68+
2. **Minimum Order Sizes**: Binance enforces minimum order sizes and notional values:
69+
70+
- Minimum order size varies by trading pair
71+
- Minimum notional value (quantity × price) must be met
72+
- The plugin validates these requirements before order execution
73+
74+
3. **Error Handling**: The plugin provides detailed error messages for:
75+
- Invalid API credentials
76+
- Insufficient balance
77+
- Invalid trading pairs
78+
- Minimum notional value not met
79+
- Other API-specific errors
80+
81+
## Service Architecture
82+
83+
The plugin is organized into specialized services:
84+
85+
- `PriceService`: Handles price-related operations
86+
- `TradeService`: Manages trading operations
87+
- `AccountService`: Handles balance and account operations
88+
- `BaseService`: Provides common functionality

packages/plugin-binance/package.json

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "@elizaos/plugin-binance",
3+
"version": "0.1.0",
4+
"type": "module",
5+
"main": "dist/index.js",
6+
"module": "dist/index.js",
7+
"types": "dist/index.d.ts",
8+
"exports": {
9+
"./package.json": "./package.json",
10+
".": {
11+
"import": {
12+
"@elizaos/source": "./src/index.ts",
13+
"types": "./dist/index.d.ts",
14+
"default": "./dist/index.js"
15+
}
16+
}
17+
},
18+
"files": [
19+
"dist"
20+
],
21+
"dependencies": {
22+
"@elizaos/core": "workspace:*",
23+
"@binance/connector": "^3.6.0",
24+
"zod": "^3.22.4"
25+
},
26+
"devDependencies": {
27+
"tsup": "8.3.5",
28+
"@types/node": "^20.0.0"
29+
},
30+
"scripts": {
31+
"build": "tsup --format esm --dts",
32+
"dev": "tsup --format esm --dts --watch",
33+
"lint": "eslint --fix --cache ."
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import {
2+
ActionExample,
3+
composeContext,
4+
elizaLogger,
5+
generateObjectDeprecated,
6+
HandlerCallback,
7+
IAgentRuntime,
8+
Memory,
9+
ModelClass,
10+
State,
11+
type Action,
12+
} from "@elizaos/core";
13+
import { BinanceService } from "../services";
14+
15+
const priceCheckTemplate = `Look at ONLY your LAST RESPONSE message in this conversation, where you just said which cryptocurrency price you would check.
16+
Based on ONLY that last message, provide the trading symbol.
17+
18+
For example:
19+
- If your last message was "I'll check the current Ethereum price..." -> return "ETH"
20+
- If your last message was "I'll check the current Solana price..." -> return "SOL"
21+
- If your last message was "I'll check the current Bitcoin price..." -> return "BTC"
22+
23+
\`\`\`json
24+
{
25+
"symbol": "<symbol from your LAST response only>",
26+
"quoteCurrency": "<quote currency from your LAST response, or USDT if none mentioned>"
27+
}
28+
\`\`\`
29+
30+
Last part of conversation:
31+
{{recentMessages}}`;
32+
33+
export const priceCheck: Action = {
34+
name: "GET_PRICE",
35+
similes: [
36+
"CHECK_PRICE",
37+
"PRICE_CHECK",
38+
"GET_CRYPTO_PRICE",
39+
"CRYPTO_PRICE",
40+
"CHECK_CRYPTO_PRICE",
41+
"PRICE_LOOKUP",
42+
"CURRENT_PRICE",
43+
],
44+
description: "Get current price information for a cryptocurrency pair",
45+
validate: async () => true, // Public endpoint
46+
handler: async (
47+
runtime: IAgentRuntime,
48+
message: Memory,
49+
state: State,
50+
_options: Record<string, unknown>,
51+
callback?: HandlerCallback
52+
): Promise<boolean> => {
53+
try {
54+
// Initialize or update state
55+
state = !state
56+
? await runtime.composeState(message)
57+
: await runtime.updateRecentMessageState(state);
58+
59+
const context = composeContext({
60+
state,
61+
template: priceCheckTemplate,
62+
});
63+
64+
const rawContent = await generateObjectDeprecated({
65+
runtime,
66+
context,
67+
modelClass: ModelClass.SMALL,
68+
});
69+
70+
if (!rawContent?.symbol) {
71+
throw new Error(
72+
"Could not determine which cryptocurrency to check"
73+
);
74+
}
75+
76+
// Ensure the content has the required shape
77+
const content = {
78+
symbol: rawContent.symbol.toString().toUpperCase().trim(),
79+
quoteCurrency: (rawContent.quoteCurrency || "USDT")
80+
.toString()
81+
.toUpperCase()
82+
.trim(),
83+
};
84+
85+
if (content.symbol.length < 2 || content.symbol.length > 10) {
86+
throw new Error("Invalid cryptocurrency symbol");
87+
}
88+
89+
const binanceService = new BinanceService();
90+
const priceData = await binanceService.getPrice(content);
91+
92+
if (callback) {
93+
callback({
94+
text: `The current ${content.symbol} price is ${BinanceService.formatPrice(priceData.price)} ${content.quoteCurrency}`,
95+
content: priceData,
96+
});
97+
}
98+
99+
return true;
100+
} catch (error) {
101+
elizaLogger.error("Error in price check:", error);
102+
if (callback) {
103+
const errorMessage = error.message.includes("Invalid API key")
104+
? "Unable to connect to Binance API"
105+
: error.message.includes("Invalid symbol")
106+
? `Sorry, could not find price for the cryptocurrency symbol you provided`
107+
: `Sorry, I encountered an error: ${error.message}`;
108+
109+
callback({
110+
text: errorMessage,
111+
content: { error: error.message },
112+
});
113+
}
114+
return false;
115+
}
116+
},
117+
examples: [
118+
[
119+
{
120+
user: "{{user1}}",
121+
content: {
122+
text: "What's the current price of Bitcoin?",
123+
},
124+
},
125+
{
126+
user: "{{agent}}",
127+
content: {
128+
text: "I'll check the current Bitcoin price for you right away.",
129+
action: "GET_PRICE",
130+
},
131+
},
132+
{
133+
user: "{{agent}}",
134+
content: {
135+
text: "The current BTC price is 42,150.25 USDT",
136+
},
137+
},
138+
],
139+
[
140+
{
141+
user: "{{user1}}",
142+
content: {
143+
text: "Can you check ETH price in EUR?",
144+
},
145+
},
146+
{
147+
user: "{{agent}}",
148+
content: {
149+
text: "I'll fetch the current Ethereum price in euros for you.",
150+
action: "GET_PRICE",
151+
},
152+
},
153+
{
154+
user: "{{agent}}",
155+
content: {
156+
text: "The current ETH price is 2,245.80 EUR",
157+
},
158+
},
159+
],
160+
] as ActionExample[][],
161+
} as Action;

0 commit comments

Comments
 (0)