A lightweight and extensible rule engine for evaluating conditions on Ethereum Virtual Machine (EVM) accounts and contracts. Define custom rules to check wallet balances, contract balances, ERC-20 token holdings, transaction counts, NFT ownership, and more.
Compatible with Node and browser environments.
- Wallet Balance: Validate that an account's ETH balance meets specific criteria.
- Contract Balance: Ensure a contract holds a required amount of ETH.
- ERC20 Balance: Check if an account holds a sufficient balance of a given ERC20 token.
- Transaction Count: Verify that an account’s number of transactions (nonce) meets expectations.
- NFT Ownership: Determine if an account owns at least one NFT or a specific NFT token.
- Address Type Verification: Confirm whether an address is a contract or an externally owned account (EOA).
- Contract Call Evaluation: Execute contract functions and evaluate their results against expected outcomes.
- Dynamic Rule Loading: Easily load and export rules from JSON definitions.
npm install evm-rule-engine
The following example shows how to set up the rule engine, add a rule, and evaluate an EVM address:
import { ethers } from 'ethers'
import { EVMRuleEngine, walletBalance, Networks } from 'evm-rule-engine'
// Configure the network (example using a local Anvil instance)
const networks: Networks = [
{
provider: new ethers.JsonRpcProvider('http://127.0.0.1:8545'),
chainId: '31337'
}
]
// Create an instance of the rule engine with the network configuration
const engine = new EVMRuleEngine({ networks })
// Add a wallet balance rule: check if the wallet has at least 1 ETH
engine.addRule(
walletBalance(networks, '31337', {
value: ethers.parseEther('1'),
compareType: 'gte'
})
)
// Evaluate all rules against a given address
const address = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
engine.evaluate(address)
.then(result => {
console.log('Evaluation Result:', result)
})
.catch(error => {
console.error('Error evaluating rules:', error)
})
Rules can also be defined in JSON format and loaded dynamically using the createRulesFromDefinitions
function:
import { createRulesFromDefinitions } from 'evm-rule-engine'
// Define rule JSON objects
const ruleDefinitions = [
{ type: 'walletBalance', chainId: '31337', params: { value: ethers.parseEther('1'), compareType: 'gte' } }
]
// Create rule instances from the JSON definitions and add them to the engine
const rules = createRulesFromDefinitions(networks, ruleDefinitions)
engine.addRules(rules)
// Export rules as JSON definitions
console.log(engine.exportRulesAsJsonString())
This project uses Mocha and Chai for testing. Some tests require one or more local Anvil instances.
Start Anvil on port 8545 with chain ID 31337
:
anvil --port 8545 --chain-id 31337
Start another instance on port 8546 with chain ID 31338
:
anvil --port 8546 --chain-id 31338
Run the tests with:
npm run test
If your rules interact with Solidity contracts, build them using Forge:
npm run build:contract
Lint the Code:
npm run lint
Build the Project:
npm run build
Other scripts available in the package.json include test coverage and dependency checks.
Contributions are welcome! Feel free to open issues or submit pull requests to improve the engine, add new features, or fix bugs.
This project is dual-licensed under the Apache-2.0 or MIT license.