-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1464 from elizaOS/thomas/cronos-zkevm
feat: Adding plugin for Cronos ZKEVM
- Loading branch information
Showing
10 changed files
with
366 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"name": "@elizaos/plugin-cronoszkevm", | ||
"version": "0.1.4-alpha.3", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"types": "dist/index.d.ts", | ||
"dependencies": { | ||
"@elizaos/core": "workspace:*", | ||
"@elizaos/plugin-trustdb": "workspace:*", | ||
"tsup": "^8.3.5", | ||
"web3": "^4.15.0", | ||
"web3-plugin-zksync": "^1.0.8" | ||
}, | ||
"scripts": { | ||
"build": "tsup --format esm --dts" | ||
}, | ||
"peerDependencies": { | ||
"whatwg-url": "7.1.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
import { | ||
ActionExample, | ||
Content, | ||
HandlerCallback, | ||
IAgentRuntime, | ||
Memory, | ||
ModelClass, | ||
State, | ||
type Action, | ||
elizaLogger, | ||
composeContext, | ||
generateObject, | ||
} from "@elizaos/core"; | ||
import { validateCronosZkevmConfig } from "../enviroment"; | ||
|
||
import { Web3 } from "web3"; | ||
import { | ||
ZKsyncPlugin, | ||
ZKsyncWallet, | ||
types, | ||
Web3ZKsyncL2, | ||
} from "web3-plugin-zksync"; | ||
|
||
export interface TransferContent extends Content { | ||
tokenAddress: string; | ||
recipient: string; | ||
amount: string | number; | ||
} | ||
|
||
export function isTransferContent( | ||
content: TransferContent | ||
): content is TransferContent { | ||
// Validate types | ||
const validTypes = | ||
typeof content.tokenAddress === "string" && | ||
typeof content.recipient === "string" && | ||
(typeof content.amount === "string" || | ||
typeof content.amount === "number"); | ||
if (!validTypes) { | ||
return false; | ||
} | ||
|
||
// Validate addresses | ||
const validAddresses = | ||
content.tokenAddress.startsWith("0x") && | ||
content.tokenAddress.length === 42 && | ||
content.recipient.startsWith("0x") && | ||
content.recipient.length === 42; | ||
|
||
return validAddresses; | ||
} | ||
|
||
const transferTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. | ||
Here are several frequently used addresses. Use these for the corresponding tokens: | ||
- ZKCRO/zkCRO: 0x000000000000000000000000000000000000800A | ||
- USDC/usdc: 0xaa5b845f8c9c047779bedf64829601d8b264076c | ||
- ETH/eth: 0x898b3560affd6d955b1574d87ee09e46669c60ea | ||
Example response: | ||
\`\`\`json | ||
{ | ||
"tokenAddress": "0xaa5b845f8c9c047779bedf64829601d8b264076c", | ||
"recipient": "0xCCa8009f5e09F8C5dB63cb0031052F9CB635Af62", | ||
"amount": "1000" | ||
} | ||
\`\`\` | ||
{{recentMessages}} | ||
Given the recent messages, extract the following information about the requested token transfer: | ||
- Token contract address | ||
- Recipient wallet address | ||
- Amount to transfer | ||
Respond with a JSON markdown block containing only the extracted values.`; | ||
|
||
export default { | ||
name: "SEND_TOKEN", | ||
similes: [ | ||
"TRANSFER_TOKEN_ON_CRONOSZKEVM", | ||
"TRANSFER_TOKENS_ON_CRONOSZK", | ||
"SEND_TOKENS_ON_CRONOSZKEVM", | ||
"SEND_TOKENS_ON_CRONOSZK", | ||
"SEND_ETH_ON_CRONOSZKEVM", | ||
"SEND_ETH_ON_CRONOSZK", | ||
"PAY_ON_CRONOSZKEVM", | ||
"PAY_ON_CRONOSZK", | ||
], | ||
validate: async (runtime: IAgentRuntime, message: Memory) => { | ||
await validateCronosZkevmConfig(runtime); | ||
return true; | ||
}, | ||
description: "Transfer tokens from the agent's wallet to another address", | ||
handler: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state: State, | ||
_options: { [key: string]: unknown }, | ||
callback?: HandlerCallback | ||
): Promise<boolean> => { | ||
elizaLogger.log("Starting SEND_TOKEN handler..."); | ||
|
||
// Initialize or update state | ||
if (!state) { | ||
state = (await runtime.composeState(message)) as State; | ||
} else { | ||
state = await runtime.updateRecentMessageState(state); | ||
} | ||
|
||
// Compose transfer context | ||
const transferContext = composeContext({ | ||
state, | ||
template: transferTemplate, | ||
}); | ||
|
||
// Generate transfer content | ||
const content = await generateObject({ | ||
runtime, | ||
context: transferContext, | ||
modelClass: ModelClass.SMALL, | ||
}); | ||
|
||
// Validate transfer content | ||
if (!isTransferContent(content)) { | ||
console.error("Invalid content for TRANSFER_TOKEN action."); | ||
if (callback) { | ||
callback({ | ||
text: "Unable to process transfer request. Invalid content provided.", | ||
content: { error: "Invalid transfer content" }, | ||
}); | ||
} | ||
return false; | ||
} | ||
|
||
try { | ||
const PRIVATE_KEY = runtime.getSetting("CRONOSZKEVM_PRIVATE_KEY")!; | ||
const PUBLIC_KEY = runtime.getSetting("CRONOSZKEVM_ADDRESS")!; | ||
|
||
const web3: Web3 = new Web3(/* optional L1 provider */); | ||
|
||
web3.registerPlugin( | ||
new ZKsyncPlugin( | ||
new Web3ZKsyncL2("https://mainnet.zkevm.cronos.org") | ||
) | ||
); | ||
|
||
const smartAccount = new web3.ZKsync.SmartAccount({ | ||
address: PUBLIC_KEY, | ||
secret: "0x" + PRIVATE_KEY, | ||
}); | ||
|
||
const transferTx = await smartAccount.transfer({ | ||
to: content.recipient, | ||
token: content.tokenAddress, | ||
amount: web3.utils.toWei(content.amount, "ether"), | ||
}); | ||
|
||
const receipt = await transferTx.wait(); | ||
|
||
elizaLogger.success( | ||
"Transfer completed successfully! tx: " + | ||
receipt.transactionHash | ||
); | ||
if (callback) { | ||
callback({ | ||
text: | ||
"Transfer completed successfully! tx: " + | ||
receipt.transactionHash, | ||
content: {}, | ||
}); | ||
} | ||
|
||
return true; | ||
} catch (error) { | ||
elizaLogger.error("Error during token transfer:", error); | ||
if (callback) { | ||
callback({ | ||
text: `Error transferring tokens: ${error.message}`, | ||
content: { error: error.message }, | ||
}); | ||
} | ||
return false; | ||
} | ||
}, | ||
|
||
examples: [ | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Send 100 USDC to 0xCCa8009f5e09F8C5dB63cb0031052F9CB635Af62", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "Sure, I'll send 100 USDC to that address now.", | ||
action: "SEND_TOKEN", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "Successfully sent 100 USDC to 0xCCa8009f5e09F8C5dB63cb0031052F9CB635Af62\nTransaction: 0x4fed598033f0added272c3ddefd4d83a521634a738474400b27378db462a76ec", | ||
}, | ||
}, | ||
], | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Please send 100 ZKCRO tokens to 0xbD8679cf79137042214fA4239b02F4022208EE82", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "Of course. Sending 100 ZKCRO to that address now.", | ||
action: "SEND_TOKEN", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "Successfully sent 100 ZKCRO to 0xbD8679cf79137042214fA4239b02F4022208EE82\nTransaction: 0x0b9f23e69ea91ba98926744472717960cc7018d35bc3165bdba6ae41670da0f0", | ||
}, | ||
}, | ||
], | ||
] as ActionExample[][], | ||
} as Action; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { IAgentRuntime } from "@elizaos/eliza"; | ||
import { z } from "zod"; | ||
|
||
export const CronosZkEVMEnvSchema = z.object({ | ||
CRONOSZKEVM_ADDRESS: z.string().min(1, "Cronos zkEVM address is required"), | ||
CRONOSZKEVM_PRIVATE_KEY: z | ||
.string() | ||
.min(1, "Cronos zkEVM private key is required"), | ||
}); | ||
|
||
export type CronoszkEVMConfig = z.infer<typeof CronosZkEVMEnvSchema>; | ||
|
||
export async function validateCronosZkevmConfig( | ||
runtime: IAgentRuntime | ||
): Promise<CronoszkEVMConfig> { | ||
try { | ||
const config = { | ||
CRONOSZKEVM_ADDRESS: | ||
runtime.getSetting("CRONOSZKEVM_ADDRESS") || | ||
process.env.CRONOSZKEVM_ADDRESS, | ||
CRONOSZKEVM_PRIVATE_KEY: | ||
runtime.getSetting("CRONOSZKEVM_PRIVATE_KEY") || | ||
process.env.CRONOSZKEVM_PRIVATE_KEY, | ||
}; | ||
|
||
return CronosZkEVMEnvSchema.parse(config); | ||
} catch (error) { | ||
if (error instanceof z.ZodError) { | ||
const errorMessages = error.errors | ||
.map((err) => `${err.path.join(".")}: ${err.message}`) | ||
.join("\n"); | ||
throw new Error( | ||
`CronosZkEVM configuration validation failed:\n${errorMessages}` | ||
); | ||
} | ||
throw error; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Plugin } from "@elizaos/core"; | ||
|
||
import transfer from "./actions/transfer"; | ||
|
||
export const cronosZkEVMPlugin: Plugin = { | ||
name: "cronoszkevm", | ||
description: "Cronos zkEVM plugin for Eliza", | ||
actions: [transfer], | ||
evaluators: [], | ||
providers: [], | ||
}; | ||
|
||
export default cronosZkEVMPlugin; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"extends": "../core/tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "dist", | ||
"rootDir": "src" | ||
}, | ||
"include": ["src/**/*.ts"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { defineConfig } from "tsup"; | ||
|
||
export default defineConfig({ | ||
entry: ["src/index.ts"], | ||
outDir: "dist", | ||
sourcemap: true, | ||
clean: true, | ||
format: ["esm"], // Ensure you're targeting CommonJS | ||
external: [ | ||
"dotenv", // Externalize dotenv to prevent bundling | ||
"fs", // Externalize fs to use Node.js built-in module | ||
"path", // Externalize other built-ins if necessary | ||
"@reflink/reflink", | ||
"@node-llama-cpp", | ||
"https", | ||
"http", | ||
"agentkeepalive" | ||
// Add other modules you want to externalize | ||
], | ||
}); |
Oops, something went wrong.