Skip to content

Commit 9c7cc5f

Browse files
committed
updates
1 parent 4c0910b commit 9c7cc5f

File tree

12 files changed

+1568
-120
lines changed

12 files changed

+1568
-120
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ characters/knowledge
5353
characters/qkntl_iris.character.json
5454
characters/qkntl_cipher.character.json
5555
characters/flaunchy.character.json
56+
characters/swapr.character.json
5657

5758
packages/core/src/providers/cache
5859
packages/core/src/providers/cache/*

Dockerfile

+78-3
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,76 @@ RUN apt-get update && \
143143
apt-get clean && \
144144
rm -rf /var/lib/apt/lists/*
145145

146+
# Create Chromium stealth wrapper
147+
RUN echo '#!/bin/bash\nexec /usr/bin/chromium \
148+
--disable-blink-features=AutomationControlled \
149+
--disable-features=IsolateOrigins,site-per-process \
150+
--disable-dev-shm-usage \
151+
--no-sandbox \
152+
--incognito \
153+
--disable-extensions \
154+
--disable-plugins \
155+
--disable-notifications \
156+
--disable-infobars \
157+
--window-size=1920,1080 \
158+
--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" \
159+
"$@"' > /usr/local/bin/chromium-stealth && \
160+
chmod +x /usr/local/bin/chromium-stealth && \
161+
ln -sf /usr/local/bin/chromium-stealth /usr/bin/chromium-stealth
162+
163+
# Configure environment to use the stealth wrapper
164+
ENV PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/local/bin/chromium-stealth
165+
166+
# Create a browser profile to make it look more like a real user
167+
RUN mkdir -p /root/.config/chromium/Default && \
168+
echo '{\
169+
"profile": {\
170+
"default_content_setting_values": {\
171+
"images": 1,\
172+
"javascript": 1,\
173+
"cookies": 1\
174+
},\
175+
"password_manager_enabled": false,\
176+
"exit_type": "Normal",\
177+
"exited_cleanly": true\
178+
},\
179+
"homepage": "https://www.google.com",\
180+
"session": {\
181+
"restore_on_startup": 4,\
182+
"startup_urls": ["https://www.google.com"]\
183+
},\
184+
"browser": {\
185+
"check_default_browser": false,\
186+
"custom_chrome_frame": true\
187+
}\
188+
}' > /root/.config/chromium/Default/Preferences
189+
190+
# Add D-Bus initialization helper
191+
RUN echo '#!/bin/bash\n\
192+
# Wait for D-Bus to be fully initialized\n\
193+
wait_for_dbus() {\n\
194+
local max_attempts=30\n\
195+
local attempt=0\n\
196+
echo "Waiting for D-Bus to initialize..."\n\
197+
while [ $attempt -lt $max_attempts ]; do\n\
198+
if dbus-send --system --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames > /dev/null 2>&1; then\n\
199+
echo "D-Bus is ready!"\n\
200+
return 0\n\
201+
fi\n\
202+
attempt=$((attempt+1))\n\
203+
echo "D-Bus not ready, waiting... (${attempt}/${max_attempts})"\n\
204+
sleep 1\n\
205+
done\n\
206+
echo "D-Bus initialization timed out!"\n\
207+
return 1\n\
208+
}\n\
209+
\n\
210+
# Main execution\n\
211+
wait_for_dbus\n\
212+
exec "$@"\n\
213+
' > /usr/local/bin/dbus-init && \
214+
chmod +x /usr/local/bin/dbus-init
215+
146216
# Install pnpm, PM2, and Google Cloud SDK
147217
RUN npm install -g pnpm@9.4.0 pm2@latest && \
148218
apt-get update && \
@@ -174,6 +244,9 @@ COPY --from=builder /app/scripts ./scripts
174244
COPY --from=builder /var/lib/dbus/machine-id /var/lib/dbus/
175245
COPY --from=builder /usr/share/dbus-1/services/org.chromium.SessionManager.service /usr/share/dbus-1/services/
176246

247+
# Update D-Bus configuration to use the stealth wrapper
248+
RUN sed -i 's|Exec=/usr/bin/chromium --no-sandbox|Exec=/usr/local/bin/chromium-stealth|g' /usr/share/dbus-1/services/org.chromium.SessionManager.service
249+
177250
# Create necessary directories
178251
RUN mkdir -p characters && \
179252
mkdir -p characters/knowledge
@@ -187,7 +260,7 @@ RUN service cron start
187260
# Expose necessary ports
188261
EXPOSE 3000 5173
189262

190-
# CMD that fetches and runs the entrypoint script
263+
# CMD that fetches and runs the entrypoint script with D-Bus initialization
191264
CMD sh -c 'rm -f /run/dbus/pid && \
192265
# Create necessary directories for D-Bus
193266
mkdir -p /run/dbus && \
@@ -197,13 +270,15 @@ CMD sh -c 'rm -f /run/dbus/pid && \
197270
if [ ! -f /var/lib/dbus/machine-id ]; then \
198271
dbus-uuidgen > /var/lib/dbus/machine-id; \
199272
fi && \
200-
# Create the Chrome D-Bus service file if it doesn't exist
273+
# Create the Chrome D-Bus service file if it doesnt exist
201274
mkdir -p /usr/share/dbus-1/services && \
202275
if [ ! -f /usr/share/dbus-1/services/org.chromium.SessionManager.service ]; then \
203-
echo "[D-BUS Service]\nName=org.chromium.SessionManager\nExec=/usr/bin/chromium --no-sandbox\nUser=root" > /usr/share/dbus-1/services/org.chromium.SessionManager.service; \
276+
echo "[D-BUS Service]\nName=org.chromium.SessionManager\nExec=/usr/local/bin/chromium-stealth\nUser=root" > /usr/share/dbus-1/services/org.chromium.SessionManager.service; \
204277
fi && \
205278
# Start D-Bus daemon
206279
dbus-daemon --system --fork && \
280+
# Wait for D-Bus to be fully initialized
281+
/usr/local/bin/dbus-init \
207282
# Fetch and run the entrypoint script
208283
echo "Fetching latest container entrypoint script..." && \
209284
gsutil cp "gs://${AGENTS_BUCKET_NAME}/_project-files/container-entrypoint.sh" /app/container-entrypoint.sh && \

agent/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import { imgflipPlugin } from "@elizaos/plugin-imgflip";
5050
import { quickIntelPlugin } from "@elizaos/plugin-quick-intel";
5151
import { flaunchPlugin } from "@elizaos/plugin-flaunch";
5252
import { rssPlugin } from "@elizaos/plugin-rss";
53+
import { socialDexPlugin } from "@elizaos/plugin-social-dex";
5354

5455
const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
5556
const __dirname = path.dirname(__filename); // get the name of the directory
@@ -340,6 +341,7 @@ async function handlePluginImporting(plugins: string[]) {
340341
importedPlugin.default || importedPlugin[functionName]
341342
);
342343
} catch (importError) {
344+
console.log('error importing plugin',importError)
343345
elizaLogger.error(
344346
`Failed to import plugin: ${plugin}`,
345347
importError

packages/client-twitter-qi/src/base.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,10 @@ export class ClientBase extends EventEmitter {
239239
if (ClientBase._twitterClients[username]) {
240240
this.twitterClient = ClientBase._twitterClients[username];
241241
} else {
242-
this.twitterClient = new Scraper();
242+
this.twitterClient = new Scraper({
243+
transform: {},
244+
245+
});
243246
ClientBase._twitterClients[username] = this.twitterClient;
244247
}
245248

packages/plugin-social-dex/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
"dependencies": {
2222
"@elizaos/core": "workspace:*",
2323
"@privy-io/server-auth": "^1.18.11",
24+
"@getpara/server-sdk": "^1.5.0",
25+
"@getpara/viem-v2-integration": "1.5.0-dev.0",
2426
"axios": "^1.8.1",
2527
"ethers": "^5.7.2",
2628
"mongodb": "^6.14.2",

packages/plugin-social-dex/src/actions/balanceAction.ts

+40-16
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getCacheKey, getRequiredFieldsForAction, isFieldComplete, formatAddress
44
import { performTradeValidations } from "../utils/validation";
55
import { SecurityManager } from "../utils/securityManager";
66
import { MongoDBManager } from "../utils/mongoConfig";
7-
import { TransactionService } from "../utils/transactionService";
7+
import { TransactionService, WalletProvider } from "../utils/transactionService";
88

99
export const balanceAction: Action = {
1010
name: "CHECK_BALANCE",
@@ -59,7 +59,7 @@ export const balanceAction: Action = {
5959

6060
return validationResult.isValid;
6161
} catch (error) {
62-
elizaLogger.error(`[balanceAction] Error validating: ${error.message}`);
62+
elizaLogger.error(`[balanceAction] Error validating: ${error instanceof Error ? error.message : 'Unknown error'}`);
6363
return false;
6464
}
6565
},
@@ -70,7 +70,7 @@ export const balanceAction: Action = {
7070
options: { [key: string]: unknown; },
7171
callback: HandlerCallback
7272
) => {
73-
elizaLogger.info(`[balanceAction] Processing balance request for user ${message.userId}`);
73+
elizaLogger.info(`[balanceAction] Processing balance request for user ${message.userId} ${state.senderName}`);
7474

7575
// Initialize MongoDB
7676
const mongodb = new MongoDBManager(runtime);
@@ -112,7 +112,7 @@ export const balanceAction: Action = {
112112
// Get user wallet
113113
const userWallet = await transactionService.getOrCreateUserWallet(
114114
message.userId,
115-
platform as 'twitter' | 'farcaster' | 'discord'
115+
platform as string
116116
);
117117

118118
if (!userWallet || !userWallet.wallets || userWallet.wallets.length === 0) {
@@ -124,6 +124,9 @@ export const balanceAction: Action = {
124124
return false;
125125
}
126126

127+
// Log the wallet provider being used
128+
elizaLogger.info(`[balanceAction] Using wallet provider: ${userWallet.provider || 'Privy'}`);
129+
127130
// Get the wallet address for the specified chain
128131
const wallet = transactionService.getWalletForChain(userWallet, tradeDetails.sourceChain!);
129132
if (!wallet) {
@@ -136,7 +139,7 @@ export const balanceAction: Action = {
136139
}
137140

138141
// Fetch balances - in a production environment, you would call blockchain APIs
139-
// For this example, we're simulating the response
142+
// This fetchTokenBalances function would need to be adapted for different providers
140143
const balances = await fetchTokenBalances(wallet.address, tradeDetails.sourceChain!);
141144

142145
// Save balance results to MongoDB for user history
@@ -149,7 +152,8 @@ export const balanceAction: Action = {
149152
wallet: wallet.address,
150153
balances,
151154
timestamp: Date.now(),
152-
operation: 'balance'
155+
operation: 'balance',
156+
provider: userWallet.provider || 'privy' // Track which provider was used
153157
});
154158
}
155159

@@ -169,8 +173,8 @@ export const balanceAction: Action = {
169173
walletAddress: formatAddress(wallet.address),
170174
balances: balances,
171175
totalValue: totalValue.toFixed(2),
172-
specificToken: tradeDetails.tokenSymbol // If a specific token was requested
173-
,
176+
specificToken: tradeDetails.tokenSymbol, // If a specific token was requested
177+
provider: userWallet.provider || 'privy',
174178
bio: "",
175179
lore: "",
176180
messageDirections: "",
@@ -181,7 +185,7 @@ export const balanceAction: Action = {
181185
recentMessagesData: []
182186
},
183187
template: `
184-
You are a cryptocurrency trading assistant.
188+
You are a cryptocurrency trading assistant named Swapr.
185189
Create a friendly, concise message showing the user's token balances on {{chain}}.
186190
187191
Wallet: {{walletAddress}}
@@ -199,8 +203,10 @@ export const balanceAction: Action = {
199203
200204
{{#if specificToken}}Focus on providing details about {{specificToken}} specifically.{{/if}}
201205
202-
Keep your response under 280 characters but make sure to include the most valuable tokens.
203-
Use crypto-related emojis (💰, 🪙, 💎, 📈) and format numbers nicely.
206+
Present the information in a clean, organized way using emoji indicators (💰, 🪙, 💎, 📈) for easy reading.
207+
208+
If balances are being retrieved using Para, mention that this is using the multi-chain secure wallet infrastructure.
209+
If using Privy, don't mention the wallet provider.
204210
`,
205211
templatingEngine: "handlebars"
206212
});
@@ -219,7 +225,8 @@ export const balanceAction: Action = {
219225
chain: tradeDetails.sourceChain,
220226
walletAddress: wallet.address,
221227
balances: balances,
222-
totalValue: totalValue
228+
totalValue: totalValue,
229+
provider: userWallet.provider
223230
}
224231
});
225232

@@ -245,7 +252,7 @@ export const balanceAction: Action = {
245252
}
246253
},
247254
{
248-
user: "TradingAgent",
255+
user: "Swapr",
249256
content: {
250257
text: "I'll check your token balances on Base.",
251258
action: "CHECK_BALANCE"
@@ -260,12 +267,27 @@ export const balanceAction: Action = {
260267
}
261268
},
262269
{
263-
user: "TradingAgent",
270+
user: "Swapr",
264271
content: {
265272
text: "💰 Your Arbitrum balance:\n- ETH: 0.423 ($1,269)\n- USDC: 150.00 ($150)\n- ARB: 75.5 ($56.63)\n\nTotal Value: $1,475.63",
266273
action: "BALANCE_SUCCESS"
267274
}
268275
}
276+
],
277+
[
278+
{
279+
user: "{{user1}}",
280+
content: {
281+
text: "Can I check my Solana wallet balance?"
282+
}
283+
},
284+
{
285+
user: "Swapr",
286+
content: {
287+
text: "🪙 Here's your Solana wallet:\n- SOL: 5.32 ($956.76)\n- USDC: 125.45 ($125.45)\n\nTotal Value: $1,082.21",
288+
action: "BALANCE_SUCCESS"
289+
}
290+
}
269291
]
270292
]
271293
};
@@ -325,8 +347,10 @@ async function fetchTokenBalances(address: string, chain: string): Promise<Array
325347
{ symbol: 'USDC', address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E', decimals: 6, minAmount: 50, maxAmount: 500, usdPrice: 1 }
326348
],
327349
'solana': [
328-
{ symbol: 'SOL', address: 'So11111111111111111111111111111111111111112', decimals: 9, minAmount: 1, maxAmount: 20, usdPrice: 100 },
329-
{ symbol: 'USDC', address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', decimals: 6, minAmount: 50, maxAmount: 500, usdPrice: 1 }
350+
{ symbol: 'SOL', address: 'So11111111111111111111111111111111111111112', decimals: 9, minAmount: 1, maxAmount: 20, usdPrice: 180 },
351+
{ symbol: 'USDC', address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', decimals: 6, minAmount: 50, maxAmount: 500, usdPrice: 1 },
352+
{ symbol: 'BONK', address: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263', decimals: 5, minAmount: 1000000, maxAmount: 10000000, usdPrice: 0.00003 },
353+
{ symbol: 'JUP', address: 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN', decimals: 6, minAmount: 100, maxAmount: 1000, usdPrice: 0.80 }
330354
]
331355
};
332356

packages/plugin-social-dex/src/index.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ export const socialDexPlugin: Plugin = {
1313
name: "Social DEX Plugin",
1414
description: "Plugin for simple, complex, AI converstational DEX and normal wallet operations.",
1515
actions: [
16-
fullTradeAction, // One-shot action for complex trade requests
17-
complexTradeAction, // Complex actions involving multiple steps/transactions
18-
buyAction, // Buy tokens on a specific chain
19-
sellAction, // Sell tokens on a specific chain
20-
sendAction, // Send tokens to another user
21-
bridgeAction, // Bridge tokens between chains
16+
//fullTradeAction, // One-shot action for complex trade requests
17+
//complexTradeAction, // Complex actions involving multiple steps/transactions
18+
//buyAction, // Buy tokens on a specific chain
19+
//sellAction, // Sell tokens on a specific chain
20+
//sendAction, // Send tokens to another user
21+
//bridgeAction, // Bridge tokens between chains
2222
balanceAction // Check token balances
2323
],
2424
evaluators: [tradeEvaluator],

packages/plugin-social-dex/src/providers/tradeProvider.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { MongoDBManager } from "../utils/mongoConfig";
1111
*/
1212
export const tradeProvider: Provider = {
1313
get: async (runtime: IAgentRuntime, message: Memory, state?: State) => {
14-
elizaLogger.info(`[tradeProvider] Running provider for message from ${message.userId}`);
14+
elizaLogger.info(`[tradeProvider] Running provider for message from ${message.userId} ${state.senderName} ${state.actorsData}`);
1515

1616
// Initialize MongoDB connection
1717
const mongodb = new MongoDBManager(runtime);
@@ -28,6 +28,8 @@ export const tradeProvider: Provider = {
2828
// Get platform information
2929
const isFarcaster = message.content?.source === 'farcaster';
3030
const isTwitter = message.content?.source === 'twitter';
31+
const isTelegram = message.content?.source === 'telegram';
32+
const isDiscord = message.content?.source === 'discord';
3133

3234
// Initial context with supported chains and actions information
3335
let status = `# IMPORTANT SYSTEM CONTEXT FOR RESPONSE\n`;

0 commit comments

Comments
 (0)