Skip to content

Commit d51ab66

Browse files
chuasonglin1995coderabbitai[bot]wtfsayo
authored
feat: 0x plugin (#2329)
* draft commit * remove useless file * update readme * Update packages/plugin-0x/src/EVMtokenRegistry.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update packages/plugin-0x/src/EVMtokenRegistry.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update packages/plugin-0x/src/actions/swap.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update packages/plugin-0x/src/actions/getIndicativePrice.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update packages/plugin-0x/src/actions/getQuote.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update packages/plugin-0x/src/hooks.ts/useGetWalletClient.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * refactor according to codeRabbit * fix syntax error, remove mode=json from Anthropic * remove unnecessary logging * remove changes to mode=json for generation * remove ai from packagejson, its in core/package.json already * resolve pnpm-lock * Update pnpm-lock.yaml --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Sayo <hi@sayo.wtf>
1 parent cac3912 commit d51ab66

18 files changed

+2024
-45
lines changed

.env.example

+4
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,10 @@ AKASH_MANIFEST_VALIDATION_LEVEL=strict
659659
QUAI_PRIVATE_KEY=
660660
QUAI_RPC_URL=https://rpc.quai.network
661661

662+
# 0x
663+
ZERO_EX_API_KEY=
664+
ALCHEMY_HTTP_TRANSPORT_URL=
665+
662666
# Instagram Configuration
663667
INSTAGRAM_DRY_RUN=false
664668
INSTAGRAM_USERNAME= # Account username

agent/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ import { zksyncEraPlugin } from "@elizaos/plugin-zksync-era";
119119

120120
import { nvidiaNimPlugin } from "@elizaos/plugin-nvidia-nim";
121121

122+
import { zxPlugin } from "@elizaos/plugin-0x";
122123
import Database from "better-sqlite3";
123124
import fs from "fs";
124125
import net from "net";
@@ -1081,6 +1082,7 @@ export async function createAgent(
10811082
getSecret(character, "RESERVOIR_API_KEY")
10821083
? createNFTCollectionsPlugin()
10831084
: null,
1085+
getSecret(character, "ZERO_EX_API_KEY") ? zxPlugin : null,
10841086
getSecret(character, "PYTH_TESTNET_PROGRAM_KEY") ||
10851087
getSecret(character, "PYTH_MAINNET_PROGRAM_KEY")
10861088
? pythDataPlugin

packages/core/src/generation.ts

+41-22
Original file line numberDiff line numberDiff line change
@@ -574,8 +574,14 @@ export async function generateText({
574574
const openai = createOpenAI({
575575
apiKey,
576576
baseURL: endpoint,
577-
fetch: async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
578-
const url = typeof input === 'string' ? input : input.toString();
577+
fetch: async (
578+
input: RequestInfo | URL,
579+
init?: RequestInit
580+
): Promise<Response> => {
581+
const url =
582+
typeof input === "string"
583+
? input
584+
: input.toString();
579585
const chain_id =
580586
runtime.getSetting("ETERNALAI_CHAIN_ID") || "45762";
581587

@@ -588,9 +594,11 @@ export async function generateText({
588594

589595
const fetching = await runtime.fetch(url, options);
590596

591-
if (parseBooleanFromText(
592-
runtime.getSetting("ETERNALAI_LOG")
593-
)) {
597+
if (
598+
parseBooleanFromText(
599+
runtime.getSetting("ETERNALAI_LOG")
600+
)
601+
) {
594602
elizaLogger.info(
595603
"Request data: ",
596604
JSON.stringify(options, null, 2)
@@ -1226,30 +1234,35 @@ export async function generateText({
12261234
messages: [
12271235
{
12281236
role: "system",
1229-
content: runtime.character.system ?? settings.SYSTEM_PROMPT ?? "You are a helpful assistant"
1237+
content:
1238+
runtime.character.system ??
1239+
settings.SYSTEM_PROMPT ??
1240+
"You are a helpful assistant",
12301241
},
12311242
{
12321243
role: "user",
1233-
content: context
1234-
}
1244+
content: context,
1245+
},
12351246
],
12361247
max_tokens: max_response_length,
1237-
stream: false
1248+
stream: false,
12381249
};
12391250

1240-
const fetchResponse = await runtime.fetch(endpoint+'/llm', {
1251+
const fetchResponse = await runtime.fetch(endpoint + "/llm", {
12411252
method: "POST",
12421253
headers: {
1243-
"accept": "text/event-stream",
1254+
accept: "text/event-stream",
12441255
"Content-Type": "application/json",
1245-
"Authorization": "Bearer eliza-app-llm"
1256+
Authorization: "Bearer eliza-app-llm",
12461257
},
1247-
body: JSON.stringify(requestBody)
1258+
body: JSON.stringify(requestBody),
12481259
});
12491260

12501261
if (!fetchResponse.ok) {
12511262
const errorText = await fetchResponse.text();
1252-
throw new Error(`Livepeer request failed (${fetchResponse.status}): ${errorText}`);
1263+
throw new Error(
1264+
`Livepeer request failed (${fetchResponse.status}): ${errorText}`
1265+
);
12531266
}
12541267

12551268
const json = await fetchResponse.json();
@@ -1258,8 +1271,13 @@ export async function generateText({
12581271
throw new Error("Invalid response format from Livepeer");
12591272
}
12601273

1261-
response = json.choices[0].message.content.replace(/<\|start_header_id\|>assistant<\|end_header_id\|>\n\n/, '');
1262-
elizaLogger.debug("Successfully received response from Livepeer model");
1274+
response = json.choices[0].message.content.replace(
1275+
/<\|start_header_id\|>assistant<\|end_header_id\|>\n\n/,
1276+
""
1277+
);
1278+
elizaLogger.debug(
1279+
"Successfully received response from Livepeer model"
1280+
);
12631281
break;
12641282
}
12651283

@@ -1641,8 +1659,8 @@ export const generateImage = async (
16411659
return runtime.getSetting("FAL_API_KEY");
16421660
case ModelProviderName.OPENAI:
16431661
return runtime.getSetting("OPENAI_API_KEY");
1644-
case ModelProviderName.VENICE:
1645-
return runtime.getSetting("VENICE_API_KEY");
1662+
case ModelProviderName.VENICE:
1663+
return runtime.getSetting("VENICE_API_KEY");
16461664
case ModelProviderName.LIVEPEER:
16471665
return runtime.getSetting("LIVEPEER_GATEWAY_URL");
16481666
default:
@@ -2485,12 +2503,14 @@ async function handleLivepeer({
24852503
}: ProviderOptions): Promise<GenerateObjectResult<unknown>> {
24862504
console.log("Livepeer provider api key:", apiKey);
24872505
if (!apiKey) {
2488-
throw new Error("Livepeer provider requires LIVEPEER_GATEWAY_URL to be configured");
2506+
throw new Error(
2507+
"Livepeer provider requires LIVEPEER_GATEWAY_URL to be configured"
2508+
);
24892509
}
24902510

24912511
const livepeerClient = createOpenAI({
24922512
apiKey,
2493-
baseURL: apiKey // Use the apiKey as the baseURL since it contains the gateway URL
2513+
baseURL: apiKey, // Use the apiKey as the baseURL since it contains the gateway URL
24942514
});
24952515

24962516
return await aiGenerateObject({
@@ -2503,7 +2523,6 @@ async function handleLivepeer({
25032523
});
25042524
}
25052525

2506-
25072526
// Add type definition for Together AI response
25082527
interface TogetherAIImageResponse {
25092528
data: Array<{
@@ -2556,4 +2575,4 @@ export async function generateTweetActions({
25562575
await new Promise((resolve) => setTimeout(resolve, retryDelay));
25572576
retryDelay *= 2;
25582577
}
2559-
}
2578+
}

packages/plugin-0x/README.md

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# @elizaos/plugin-0x
2+
3+
This plugin enables Eliza to interact with the 0x Protocol, providing decentralized exchange capabilities across multiple evm blockchain networks with optimized token swaps and liquidity aggregation.
4+
5+
Supported networks include:
6+
- Ethereum Mainnet
7+
- Polygon
8+
- Binance Smart Chain
9+
- Arbitrum
10+
- Optimism
11+
- Base
12+
- Linea
13+
- Scroll
14+
- Avalanche
15+
- Blast
16+
17+
## Configuration
18+
19+
Set the following environment variables:
20+
21+
```env
22+
WALLET_PRIVATE_KEY=your_private_key
23+
ZERO_EX_API_KEY=your_0x_api_key
24+
{chain}_RPC_URL=your_rpc_endpoint
25+
```
26+
27+
## Installation
28+
29+
```bash
30+
pnpm install @elizaos/plugin-0x
31+
```
32+
33+
## Usage
34+
35+
### Basic Integration
36+
37+
```typescript
38+
import { zeroExPlugin } from "@elizaos/plugin-0x";
39+
```
40+
41+
### Example Usage
42+
43+
The plugin supports natural language commands for ETH transfers:
44+
45+
```typescript
46+
"I want to convert 1 ETH to USDC on ethereum chain";
47+
"Give me the quote";
48+
"Execute it";
49+
```
50+
51+
## Available Actions
52+
53+
The plugin provides the following actions:
54+
55+
1. **GET_INDICATIVE_PRICE_0X**: Get indicative prices for token swaps
56+
- Example: "Get quote for swapping 1 ETH to USDC on Ethereum chain"
57+
- Example: "Price check for trading 100 USDT to MATIC on Polygon chain"
58+
59+
2. **GET_QUOTE_0X**: Get the quote for the swap. Quote expires in 5mins. (This action is triggered only after user has requested for an indicative price. No need to repeat the buy/sell tokens because the last indicative price will be stored in the memory)
60+
- Example: "Get quote"
61+
62+
3. **EXECUTE_SWAP_0X**: Execute token swaps. (Action is triggered only after user has gotten a quote)
63+
- Example: "Execute the swap"
64+
65+
## Security Best Practices
66+
67+
1. **Environment Variables**
68+
- Never commit private keys to version control
69+
- Use secure environment variable management
70+
- Rotate private keys periodically
71+
72+
## Contributing
73+
74+
Contributions are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information.
75+
76+
## Credits
77+
78+
This plugin integrates with:
79+
- [0x Protocol](https://0x.org/)
80+
81+
For more information about 0x capabilities:
82+
- [0x API Documentation](https://0x.org/docs/api)
83+
84+
## License
85+
86+
This plugin is part of the Eliza project. See the main project repository for license information.

packages/plugin-0x/package.json

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "@elizaos/plugin-0x",
3+
"version": "0.1.8",
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+
"scripts": {
22+
"build": "tsup --format esm --dts",
23+
"dev": "tsup --format esm --dts --watch",
24+
"test": "vitest"
25+
},
26+
"dependencies": {
27+
"@0x/swap-ts-sdk": "2.1.1"
28+
},
29+
"devDependencies": {
30+
"tsup": "^8.0.1"
31+
},
32+
"peerDependencies": {
33+
"@elizaos/core": "workspace:*",
34+
"zod": "^3.22.4"
35+
}
36+
}

0 commit comments

Comments
 (0)