Skip to content

Commit

Permalink
Merge pull request #1785 from Freytes/RabbiTrader
Browse files Browse the repository at this point in the history
feat: plugin new RabbiTrader
  • Loading branch information
wtfsayo authored Jan 8, 2025
2 parents 3854f1e + 44243da commit 235c523
Show file tree
Hide file tree
Showing 23 changed files with 2,868 additions and 29 deletions.
31 changes: 31 additions & 0 deletions packages/plugin-rabbi-trader/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "@elizaos/plugin-rabbi-trader",
"version": "0.1.5-alpha.5",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",
"dependencies": {
"@elizaos/core": "workspace:*",
"@elizaos/client-twitter":"workspace:*",
"@elizaos/plugin-solana":"workspace:*",
"@elizaos/plugin-trustdb":"workspace:*",
"@solana/web3.js": "^1.87.6",
"zod":"3.23.8",
"@goat-sdk/core": "0.3.8",
"@goat-sdk/plugin-erc20": "0.1.7",
"@goat-sdk/wallet-viem": "0.1.3",
"node-cache": "^5.1.2",
"bignumber": "1.1.0",
"bignumber.js": "9.1.2",
"@goat-sdk/plugin-coingecko":"0.1.4",
"tsup": "8.3.5",
"ws": "^8.0.0"
},
"scripts": {
"build": "tsup --format esm --dts",
"dev": "tsup --format esm --dts --watch"
},
"peerDependencies": {
"whatwg-url": "7.1.0"
}
}
179 changes: 179 additions & 0 deletions packages/plugin-rabbi-trader/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# Rabbi Trader Plugin

An automated cryptocurrency trading plugin for Solana tokens with integrated trust scoring, market analysis, and Twitter notifications.

## Features

- Automated trading on Solana blockchain
- Real-time market data analysis using DexScreener
- Trust score evaluation for tokens
- Twitter integration for trade notifications
- Safety limits and risk management
- Simulation capabilities before executing trades
- Performance tracking and trade history
- Rate limiting and cache management

## Installation

```bash
npm install @elizaos/plugin-rabbi-trader
```

## Prerequisites

The following environment variables need to be configured:

- `WALLET_PRIVATE_KEY`: Your Solana wallet private key
- `WALLET_PUBLIC_KEY`: Your Solana wallet public address
- `RPC_URL`: Solana RPC endpoint (defaults to mainnet)
- `BIRDEYE_API_KEY`: API key for Birdeye data provider
- `TWITTER_ENABLED`: Enable/disable Twitter notifications
- `TWITTER_USERNAME`: Twitter username for notifications
- `DEXSCREENER_WATCHLIST_ID`: DexScreener watchlist identifier
- `COINGECKO_API_KEY`: CoinGecko API key for additional market data

## Usage

```typescript
import createRabbiTraderPlugin from '@elizaos/plugin-rabbi-trader';
import { IAgentRuntime } from '@elizaos/core';

const plugin = await createRabbiTraderPlugin(
(key: string) => process.env[key],
runtime
);

// Plugin will automatically start monitoring and trading if enabled
```

## Configuration

### Safety Limits

The plugin includes built-in safety limits that can be configured:

```typescript
export const SAFETY_LIMITS = {
MINIMUM_TRADE: 0.01, // Minimum SOL per trade
MAX_POSITION_SIZE: 0.1, // Maximum 10% of token liquidity
MAX_SLIPPAGE: 0.05, // Maximum 5% slippage allowed
MIN_LIQUIDITY: 1000, // Minimum $1000 liquidity required
MIN_VOLUME: 2000, // Minimum $2000 24h volume required
MIN_TRUST_SCORE: 0.4, // Minimum trust score to trade
STOP_LOSS: 0.2, // 20% stop loss trigger
TAKE_PROFIT: 0.12, // Take profit at 12% gain
TRAILING_STOP: 0.2 // 20% trailing stop from highest
};
```

### Trading Parameters

Default trading parameters can be adjusted in the configuration:

```typescript
{
CHECK_INTERVAL: 5 * 60 * 1000, // Check every 5 minutes
REENTRY_DELAY: 60 * 60 * 1000, // Wait 1 hour before re-entering
MAX_ACTIVE_POSITIONS: 5, // Maximum concurrent positions
MIN_WALLET_BALANCE: 0.05 // Keep minimum 0.05 SOL in wallet
}
```

## API Integration

The plugin integrates with multiple APIs:

- **Birdeye API**: Market data and token security information
- **DexScreener**: Real-time trading data and market analysis
- **Twitter**: Trade notifications and updates
- **Jupiter**: Token swaps and liquidity aggregation

## Error Handling

The plugin includes comprehensive error handling for common scenarios:

```typescript
export const ERROR_SIGNATURES = [
{
sig: "0x13be252b",
name: "InsufficientAllowance",
description: "Token allowance too low"
},
{
sig: "0xf4d678b8",
name: "InsufficientBalance",
description: "Insufficient token balance"
},
// ... additional error signatures
];
```

## Trade Analysis

The plugin performs detailed analysis before executing trades:

1. Token security evaluation
2. Market data analysis
3. Trust score calculation
4. Liquidity assessment
5. Volume verification
6. Price movement analysis
7. Holder distribution review

## Twitter Integration

When enabled, the plugin can post trade notifications with:

- Token information
- Trade details (buy/sell price, amount)
- Trust score and risk level
- Market metrics
- Transaction signature
- Profit/loss for sells

## Caching

The plugin implements multiple caching mechanisms:

- Token analysis cache (20 minutes)
- Twitter rate limiting cache (hourly limits)
- Skip/wait cache (2 hours)
- Analysis history (24 hours)

## Development

### Building

```bash
npm run build
```

### Development Mode

```bash
npm run dev
```

## Dependencies

Key dependencies include:

- `@solana/web3.js`: Solana blockchain interaction
- `@elizaos/core`: Core agent runtime
- `@elizaos/plugin-solana`: Solana integration
- `@elizaos/plugin-trustdb`: Trust score database
- `node-cache`: Caching functionality
- `bignumber.js`: Precise number handling

## Contributing

1. Fork the repository
2. Create your feature branch
3. Commit your changes
4. Push to the branch
5. Create a new Pull Request

## License

This project is licensed under the MIT License - see the LICENSE file for details.

2 changes: 2 additions & 0 deletions packages/plugin-rabbi-trader/src/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { analyzeTradeAction } from "./actions/analyzeTrade";
export const actions = [analyzeTradeAction];
94 changes: 94 additions & 0 deletions packages/plugin-rabbi-trader/src/actions/analyzeTrade.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import {
Action,
composeContext,
elizaLogger,
generateText,
ModelClass,
parseJSONObjectFromText,
} from "@elizaOS/core";

export const analyzeTradeAction: Action = {
name: "ANALYZE_TRADE",
description: "Analyze a token for trading opportunities",
similes: [
"ANALYZE",
"ANALYZE_TOKEN",
"TRADE",
"ANALYZE_TRADE",
"EVALUATE",
"ASSESS",
],
examples: [],
validate: async () => true,
handler: async (runtime, memory, state, params, callback) => {
try {
// composeState
if (!state) {
state = await runtime.composeState(memory);
} else state = await runtime.updateRecentMessageState(state);

const tokenData = {
walletBalance: params.walletBalance,
tokenAddress: params.tokenAddress,
price: params.price,
volume: params.volume,
marketCap: params.marketCap,
liquidity: params.liquidity,
holderDistribution: params.holderDistribution,
trustScore: params.trustScore,
dexscreener: params.dexscreener,
position: params.position,
};

// Direct prompt instead of template
const prompt = `Analyze the following token data and provide a trading recommendation.
Return the response as a JSON object with the following structure:
{
"recommendation": "BUY" | "SELL" | "HOLD",
"confidence": number (0-100),
"reasoning": string,
"risks": string[],
"opportunities": string[]
}
Token Data:
${JSON.stringify(tokenData, null, 2)}`;

// Generate analysis using direct prompt
const content = await generateText({
runtime,
context: prompt,
modelClass: ModelClass.LARGE,
});

if (!content) {
throw new Error("No analysis generated");
}

elizaLogger.log(`Raw analysis response:`, content);

// Parse the response to get the recommended action
const recommendation = parseJSONObjectFromText(content);
elizaLogger.log(
`Parsed recommendation for ${params.tokenAddress}:`,
recommendation,
);

// Send result through callback
if (callback) {
await callback({
text: JSON.stringify(recommendation),
type: "analysis",
});
}

return true;
} catch (error) {
elizaLogger.error(`Analysis failed:`, {
error: error instanceof Error ? error.message : "Unknown error",
stack: error instanceof Error ? error.stack : undefined,
});
return false;
}
},
};
61 changes: 61 additions & 0 deletions packages/plugin-rabbi-trader/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
export const PROVIDER_CONFIG = {
BIRDEYE_API: "https://public-api.birdeye.so",
TOKEN_SECURITY_ENDPOINT: "/defi/token_security?address=",
TOKEN_METADATA_ENDPOINT: "/defi/v3/token/meta-data/single?address=",
MARKET_SEARCH_ENDPOINT: "/defi/v3/token/trade-data/single?address=",
TOKEN_PRICE_CHANGE_ENDPOINT:
"/defi/v3/search?chain=solana&target=token&sort_by=price_change_24h_percent&sort_type=desc&verify_token=true&markets=Raydium&limit=20",
TOKEN_VOLUME_24_CHANGE_ENDPOINT:
"/defi/v3/search?chain=solana&target=token&sort_by=volume_24h_change_percent&sort_type=desc&verify_token=true&markets=Raydium&limit=20",
TOKEN_BUY_24_CHANGE_ENDPOINT:
"/defi/v3/search?chain=solana&target=token&sort_by=buy_24h_change_percent&sort_type=desc&verify_token=true&markets=Raydium&offset=0&limit=20",

TOKEN_SECURITY_ENDPOINT_BASE: "/defi/token_security?address=",
TOKEN_METADATA_ENDPOINT_BASE: "/defi/v3/token/meta-data/single?address=",
MARKET_SEARCH_ENDPOINT_BASE: "/defi/v3/token/trade-data/single?address=",
TOKEN_PRICE_CHANGE_ENDPOINT_BASE:
"/defi/v3/search?chain=base&target=token&sort_by=price_change_24h_percent&sort_type=desc&offset=0&limit=20",
TOKEN_VOLUME_24_ENDPOINT_BASE:
"/defi/v3/search?chain=base&target=token&sort_by=volume_24h_usd&sort_type=desc&offset=2&limit=20",
TOKEN_BUY_24_ENDPOINT_BASE:
"/defi/v3/search?chain=base&target=token&sort_by=buy_24h&sort_type=desc&offset=2&limit=20",

MAX_RETRIES: 3,
RETRY_DELAY: 2000,
};

// Add configuration for enabled chains
export const CHAIN_CONFIG = {
SOLANA_ENABLED: false, // Can be controlled via settings
BASE_ENABLED: true, // Can be controlled via settings
};

// Add Base chain configuration near other export constants
export const BASE_CONFIG = {
RPC_URL: process.env.EVM_PROVIDER_URL || "https://mainnet.base.org",
ROUTER_ADDRESS: "0x327Df1E6de05895d2ab08513aaDD9313Fe505d86", // Base Uniswap V2 Router
WETH_ADDRESS: "0x4200000000000000000000000000000000000006", // Base WETH
CHAIN_ID: 8453,
// Add Aerodrome-specific addresses
AERODROME: {
WETH: "0x4200000000000000000000000000000000000006",
USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
USDT: "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
},
};

// Add 0x API configuration near other export constants
export const ZEROEX_CONFIG = {
API_URL: "https://api.0x.org",
API_KEY: process.env.ZEROEX_API_KEY || "",
QUOTE_ENDPOINT: "/swap/permit2/quote",
PRICE_ENDPOINT: "/swap/permit2/price",
SUPPORTED_CHAINS: {
BASE: 8453,
},
HEADERS: {
"Content-Type": "application/json",
"0x-api-key": process.env.ZEROEX_API_KEY || "",
"0x-version": "v2",
},
};
25 changes: 25 additions & 0 deletions packages/plugin-rabbi-trader/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export const SAFETY_LIMITS = {
MINIMUM_TRADE: 0.01, // Minimum 0.01 SOL per trade
MAX_POSITION_SIZE: 0.1, // Maximum 10% of token liquidity
MAX_SLIPPAGE: 0.05, // Maximum 5% slippage allowed
MIN_LIQUIDITY: 1000, // Minimum $1000 liquidity required
MIN_VOLUME: 2000, // Minimum $2000 24h volume required
MIN_TRUST_SCORE: 0.4, // Minimum trust score to trade
STOP_LOSS: 0.2, // 20% stop loss trigger
CHECK_INTERVAL: 5 * 60 * 1000, // Check every 5 minutes
TAKE_PROFIT: 0.12, // Take profit at 12% gain
TRAILING_STOP: 0.2, // 20% trailing stop from highest
PARTIAL_TAKE: 0.06, // Take 50% profit at 6% gain
REENTRY_DELAY: 60 * 60 * 1000, // Wait 1 hour before re-entering
MAX_ACTIVE_POSITIONS: 5, // Maximum concurrent positions
MIN_WALLET_BALANCE: 0.05, // Keep minimum 0.05 SOL in wallet
};

export const ANALYSIS_HISTORY_EXPIRY = 24 * 60 * 60 * 1000; // 24 hours in milliseconds

export const MAX_TWEETS_PER_HOUR = {
trade: 10,
market_search: 5,
};

export const MARKET_SEARCH_INTERVAL = 60 * 60 * 1000; // 1 hour in milliseconds
Loading

0 comments on commit 235c523

Please sign in to comment.