Multi-language EVM blockchain plugin for elizaOS with TypeScript, Rust, and Python implementations.
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:
| Language | Package | Status |
|---|---|---|
| TypeScript | @elizaos/plugin-evm | ✅ Production |
| Rust | elizaos-plugin-evm (crates.io) | ✅ Production |
| Python | elizaos-plugin-evm (PyPI) | ✅ Production |
- 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
| Chain | ID | Native Token |
|---|---|---|
| Ethereum Mainnet | 1 | ETH |
| Sepolia (testnet) | 11155111 | ETH |
| Base | 8453 | ETH |
| Base Sepolia | 84532 | ETH |
| Arbitrum One | 42161 | ETH |
| Optimism | 10 | ETH |
| Polygon | 137 | MATIC |
| Avalanche C-Chain | 43114 | AVAX |
| BNB Smart Chain | 56 | BNB |
| Gnosis | 100 | xDAI |
| Fantom | 250 | FTM |
| Linea | 59144 | ETH |
| Scroll | 534352 | ETH |
| zkSync Era | 324 | ETH |
bun add @elizaos/plugin-evm
# or
npm install @elizaos/plugin-evm[dependencies]
elizaos-plugin-evm = "0.1"pip install elizaos-plugin-evmimport{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");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(())}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())# 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{
"settings": {
"chains": {
"evm": ["base", "arbitrum", "optimism"]
}
}
}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 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 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)// ProposeProposeaproposaltothe0xGOVERNORgovernoronEthereumtotransfer1ETHto0xRecipient// VoteVoteFORonproposal1onthe0xGOVERNORgovernoronEthereum// QueueQueueproposal1onthe0xGOVERNORgovernoronEthereum// ExecuteExecuteproposal1onthe0xGOVERNORgovernoronEthereumAll implementations enforce strong types with fail-fast validation:
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",});fromelizaos_plugin_evmimportTransferParamsfrompydanticimportValidationErrortry:
params=TransferParams(
from_chain=SupportedChain.MAINNET,
to_address="invalid", # Fails!amount="0", # Fails!
)
exceptValidationErrorase:
print(e)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(),)?;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
# 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]"# TypeScript
npx vitest
# Rustcd rust && cargo test# Pythoncd python && pytest tests/ -vAll 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 -vbun run build
npm publishcd rust
cargo publishcd python
python -m build
twine upload dist/*See language-specific READMEs for detailed API documentation:
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
MIT - See LICENSE for details.