-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
408 additions
and
23 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,19 @@ | ||
{ | ||
"name": "@elizaos/plugin-abstract", | ||
"version": "0.1.7-alpha.1", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"types": "dist/index.d.ts", | ||
"dependencies": { | ||
"@elizaos/core": "workspace:*", | ||
"tsup": "^8.3.5", | ||
"web3": "^4.15.0", | ||
"viem": "2.21.53" | ||
}, | ||
"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,257 @@ | ||
import { | ||
ActionExample, | ||
Content, | ||
HandlerCallback, | ||
IAgentRuntime, | ||
Memory, | ||
ModelClass, | ||
State, | ||
type Action, | ||
elizaLogger, | ||
composeContext, | ||
generateObject, | ||
} from "@elizaos/core"; | ||
import { validateAbstractConfig } from "../environment"; | ||
|
||
import { Address, createWalletClient, erc20Abi, http, parseEther } from "viem"; | ||
import { abstractTestnet } from "viem/chains"; | ||
import { privateKeyToAccount } from "viem/accounts"; | ||
import { eip712WalletActions } from "viem/zksync"; | ||
import { z } from "zod"; | ||
|
||
const TransferSchema = z.object({ | ||
tokenAddress: z.string(), | ||
recipient: z.string(), | ||
amount: z.string(), | ||
}); | ||
|
||
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: | ||
- ETH/eth: 0x000000000000000000000000000000000000800A | ||
- USDC/usdc: 0xe4c7fbb0a626ed208021ccaba6be1566905e2dfc | ||
Example response: | ||
\`\`\`json | ||
{ | ||
"tokenAddress": "0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E", | ||
"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.`; | ||
|
||
const ETH_ADDRESS = "0x000000000000000000000000000000000000800A"; | ||
const ERC20_OVERRIDE_INFO = { | ||
"0xe4c7fbb0a626ed208021ccaba6be1566905e2dfc": { | ||
name: "USDC", | ||
decimals: 6, | ||
}, | ||
}; | ||
|
||
export default { | ||
name: "SEND_TOKEN", | ||
similes: [ | ||
"TRANSFER_TOKEN_ON_ABSTRACT", | ||
"TRANSFER_TOKENS_ON_ABSTRACT", | ||
"SEND_TOKENS_ON_ABSTRACT", | ||
"SEND_ETH_ON_ABSTRACT", | ||
"PAY_ON_ABSTRACT", | ||
"MOVE_TOKENS_ON_ABSTRACT", | ||
"MOVE_ETH_ON_ABSTRACT", | ||
], | ||
validate: async (runtime: IAgentRuntime, message: Memory) => { | ||
await validateAbstractConfig(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 Abstract 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, | ||
schema: TransferSchema, | ||
}) | ||
).object as unknown as TransferContent; | ||
|
||
// 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("ABSTRACT_PRIVATE_KEY")!; | ||
const account = privateKeyToAccount(`0x${PRIVATE_KEY}`); | ||
|
||
const walletClient = createWalletClient({ | ||
chain: abstractTestnet, | ||
transport: http(), | ||
}).extend(eip712WalletActions()); | ||
|
||
let hash; | ||
if ( | ||
content.tokenAddress.toLowerCase() !== ETH_ADDRESS.toLowerCase() | ||
) { | ||
// Convert amount to proper token decimals | ||
const tokenInfo = | ||
ERC20_OVERRIDE_INFO[content.tokenAddress.toLowerCase()]; | ||
const decimals = tokenInfo?.decimals ?? 18; // Default to 18 decimals if not specified | ||
const tokenAmount = | ||
BigInt(content.amount) * BigInt(10 ** decimals); | ||
|
||
// Execute ERC20 transfer | ||
hash = await walletClient.writeContract({ | ||
account, | ||
chain: abstractTestnet, | ||
address: content.tokenAddress as Address, | ||
abi: erc20Abi, | ||
functionName: "transfer", | ||
args: [content.recipient as Address, tokenAmount], | ||
}); | ||
} else { | ||
hash = await walletClient.sendTransaction({ | ||
account: account, | ||
chain: abstractTestnet, | ||
to: content.recipient as Address, | ||
value: parseEther(content.amount.toString()), | ||
kzg: undefined, | ||
}); | ||
} | ||
|
||
elizaLogger.success( | ||
"Transfer completed successfully! Transaction hash: " + hash | ||
); | ||
if (callback) { | ||
callback({ | ||
text: | ||
"Transfer completed successfully! Transaction hash: " + | ||
hash, | ||
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 0.1 ETH to 0xbD8679cf79137042214fA4239b02F4022208EE82", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "Of course. Sending 0.1 ETH to that address now.", | ||
action: "SEND_TOKEN", | ||
}, | ||
}, | ||
{ | ||
user: "{{agent}}", | ||
content: { | ||
text: "Successfully sent 0.1 ETH 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,32 @@ | ||
import { IAgentRuntime } from "@elizaos/core"; | ||
import { z } from "zod"; | ||
|
||
export const abstractEnvSchema = z.object({ | ||
ABSTRACT_ADDRESS: z.string().min(1, "Abstract address is required"), | ||
ABSTRACT_PRIVATE_KEY: z.string().min(1, "Abstract private key is required"), | ||
}); | ||
|
||
export type AbstractConfig = z.infer<typeof abstractEnvSchema>; | ||
|
||
export async function validateAbstractConfig( | ||
runtime: IAgentRuntime | ||
): Promise<AbstractConfig> { | ||
try { | ||
const config = { | ||
ABSTRACT_ADDRESS: runtime.getSetting("ABSTRACT_ADDRESS"), | ||
ABSTRACT_PRIVATE_KEY: runtime.getSetting("ABSTRACT_PRIVATE_KEY"), | ||
}; | ||
|
||
return abstractEnvSchema.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( | ||
`Abstract 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.ts"; | ||
|
||
export const abstractPlugin: Plugin = { | ||
name: "abstract", | ||
description: "Abstract Plugin for Eliza", | ||
actions: [transfer], | ||
evaluators: [], | ||
providers: [], | ||
}; | ||
|
||
export default abstractPlugin; |
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,10 @@ | ||
{ | ||
"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.