Skip to content

Repository files navigation

@elizaos/plugin-evm

Multi-language EVM blockchain plugin for elizaOS with TypeScript, Rust, and Python implementations.

Overview

This plugin provides comprehensive functionality for interacting with EVM-compatible blockchains, including token transfers, cross-chain bridging, and token swaps using LiFi integration. The plugin is available in three languages:

LanguagePackageStatus
TypeScript@elizaos/plugin-evm✅ Production
Rustelizaos-plugin-evm (crates.io)✅ Production
Pythonelizaos-plugin-evm (PyPI)✅ Production

Features

  • Multi-chain Support: Ethereum, Base, Arbitrum, Optimism, Polygon, and 10+ more chains
  • Native Token Transfers: Send ETH, MATIC, BNB, etc.
  • ERC20 Token Transfers: Send any ERC20 token
  • Cross-chain Bridging: Bridge tokens between chains via LiFi
  • Token Swaps: Exchange tokens on supported DEXs
  • DAO Governance: Propose, vote, queue, and execute proposals
  • Strong Typing: Branded types with Zod (TS), Pydantic (Python), and strongly-typed structs (Rust)
  • Fail-Fast Validation: No defensive programming - invalid data fails immediately

Supported Chains

ChainIDNative Token
Ethereum Mainnet1ETH
Sepolia (testnet)11155111ETH
Base8453ETH
Base Sepolia84532ETH
Arbitrum One42161ETH
Optimism10ETH
Polygon137MATIC
Avalanche C-Chain43114AVAX
BNB Smart Chain56BNB
Gnosis100xDAI
Fantom250FTM
Linea59144ETH
Scroll534352ETH
zkSync Era324ETH

Installation

TypeScript

bun add @elizaos/plugin-evm
# or
npm install @elizaos/plugin-evm

Rust

[dependencies]
elizaos-plugin-evm = "0.1"

Python

pip install elizaos-plugin-evm

Quick Start

TypeScript

import{evmPlugin,EvmService}from"@elizaos/plugin-evm";// Add to your agentconstagent=createAgent({plugins: [evmPlugin],});// Or use the service directlyconstservice=newEvmService();awaitservice.initialize(runtime);// Get wallet infoconstaddress=service.getAddress();constbalance=awaitservice.getBalance("mainnet");

Rust

use elizaos_plugin_evm::{EVMAdapterImpl,EVMAdapter};#[tokio::main]asyncfnmain() -> anyhow::Result<()>{let agent_id = UUID::new_v4();let private_key = std::env::var("EVM_PRIVATE_KEY")?;let adapter = EVMAdapterImpl::new(&agent_id,&private_key).await?;
adapter.init().await?;let address = adapter.get_address().await?;println!("Address: {:?}", address);Ok(())}

Python

importasynciofromelizaos_plugin_evmimportEVMWalletProvider, SupportedChainasyncdefmain():
provider=EVMWalletProvider("your_private_key")
print(f"Address: {provider.address}")
balance=awaitprovider.get_balance(SupportedChain.MAINNET)
print(f"Balance: {balance.native_balance} ETH")
asyncio.run(main())

Configuration

Environment Variables

# RequiredEVM_PRIVATE_KEY=your-private-key-here# Optional - Custom RPC URLsEVM_PROVIDER_URL=https://your-custom-mainnet-rpc-urlETHEREUM_PROVIDER_BASE=https://mainnet.base.orgETHEREUM_PROVIDER_ARBITRUM=https://arb1.arbitrum.io/rpc

Character Configuration

{
"settings": {
"chains": {
"evm": ["base", "arbitrum", "optimism"]
}
}
}

Actions

Transfer

Transfer native tokens or ERC20 tokens:

// TypeScriptTransfer1ETHto0x742d35Cc6634C0532925a3b844Bc454e4438f44eonmainnetTransfer100USDCto0x742d35Cc6634C0532925a3b844Bc454e4438f44eonbase
# Pythonfromelizaos_plugin_evmimportTransferParams, execute_transferparams=TransferParams(
from_chain=SupportedChain.MAINNET,
to_address="0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
amount="1.0",
)
tx_hash=awaitexecute_transfer(provider, params)

Swap

Swap tokens on the same chain:

// TypeScriptSwap1ETHforUSDConBase
# Pythonfromelizaos_plugin_evmimportSwapParams, execute_swapparams=SwapParams(
chain=SupportedChain.MAINNET,
from_token="0x0000000000000000000000000000000000000000", # ETHto_token="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", # USDCamount="1000000000000000000",
slippage=0.01,
)
tx_hash=awaitexecute_swap(provider, params)

Bridge

Bridge tokens between chains:

// TypeScriptBridge1ETHfromEthereumtoBase
# Pythonfromelizaos_plugin_evmimportBridgeParams, execute_bridgeparams=BridgeParams(
from_chain=SupportedChain.MAINNET,
to_chain=SupportedChain.BASE,
from_token="0x0000000000000000000000000000000000000000",
to_token="0x0000000000000000000000000000000000000000",
amount="1000000000000000000",
)
status=awaitexecute_bridge(provider, params)

DAO Governance

// ProposeProposeaproposaltothe0xGOVERNORgovernoronEthereumtotransfer1ETHto0xRecipient// VoteVoteFORonproposal1onthe0xGOVERNORgovernoronEthereum// QueueQueueproposal1onthe0xGOVERNORgovernoronEthereum// ExecuteExecuteproposal1onthe0xGOVERNORgovernoronEthereum

Type Safety

All implementations enforce strong types with fail-fast validation:

TypeScript (Zod + Branded Types)

import{ZAddress,ZTransferParams}from"@elizaos/plugin-evm";// Validated at runtimeconstaddress=ZAddress.parse("0x1234...");// Throws if invalidconstparams=ZTransferParams.parse({fromChain: "mainnet",toAddress: "0x...",amount: "1.0",});

Python (Pydantic)

fromelizaos_plugin_evmimportTransferParamsfrompydanticimportValidationErrortry:
params=TransferParams(
from_chain=SupportedChain.MAINNET,
to_address="invalid", # Fails!amount="0", # Fails!
)
exceptValidationErrorase:
print(e)

Rust (Type System)

use elizaos_plugin_evm::types::{Address,TransferParams};// Compile-time type safetylet address:Address = "0x1234...".parse()?;let params = TransferParams::new(ChainName::Mainnet,
address,"1.0".into(),)?;

Directory Structure

packages/plugin-evm/
├── typescript/ # TypeScript implementation
│ ├── actions/ # Transfer, swap, bridge actions
│ ├── providers/ # Wallet provider
│ ├── types/ # Branded types and Zod schemas
│ └── index.ts # Main entry point
├── rust/ # Rust implementation
│ ├── src/
│ │ ├── actions/ # Transfer, swap, bridge actions
│ │ ├── providers/ # Wallet adapter
│ │ ├── types.rs # Type definitions
│ │ └── lib.rs # Main entry point
│ ├── tests/ # Integration tests
│ └── Cargo.toml # Crate manifest
├── python/ # Python implementation
│ ├── elizaos_plugin_evm/
│ │ ├── actions/ # Transfer, swap, bridge actions
│ │ ├── providers/ # Wallet provider
│ │ ├── types.py # Pydantic models
│ │ └── __init__.py # Main entry point
│ ├── tests/ # Integration tests
│ └── pyproject.toml # Package manifest
├── build.ts # Build script
├── package.json # NPM manifest
└── README.md # This file

Development

Building

# TypeScript
bun run build
# Rust (native)cd rust && cargo build --release
# Rust (WASM)cd rust && cargo build --release --target wasm32-unknown-unknown --features wasm
# Pythoncd python && pip install -e ".[dev]"

Testing

# TypeScript
npx vitest
# Rustcd rust && cargo test# Pythoncd python && pytest tests/ -v

Integration Tests

All implementations include integration tests against live testnets:

# Set your testnet private keyexport EVM_PRIVATE_KEY="your_testnet_private_key"# TypeScript
bun run test:integration
# Rustcd rust && cargo test --features native -- --ignored
# Pythoncd python && pytest tests/test_integration.py -v

Publishing

TypeScript (npm)

bun run build
npm publish

Rust (crates.io)

cd rust
cargo publish

Python (PyPI)

cd python
python -m build
twine upload dist/*

API Reference

See language-specific READMEs for detailed API documentation:

Credits

This plugin integrates with:

  • Ethereum: Decentralized blockchain
  • LiFi: Cross-chain bridge and swap aggregator
  • viem: TypeScript Ethereum client
  • alloy-rs: Rust Ethereum toolkit
  • web3.py: Python Ethereum library

License

MIT - See LICENSE for details.

About

This plugin enables interaction with EVM-compatible chains, supporting token transfers, cross-chain bridging, and swaps via LiFi integration.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages