EVM Account Abstraction on Algorand via ECDSA signature verification
xChain EVM enables Ethereum wallets (MetaMask, etc.) to control Algorand accounts using an ECDSA signature verification LogicSig. Sign once with your Ethereum wallet to authorize transactions on Algorand—no seed phrases, no new wallets.
Important
The xChain Accounts protocol is in Beta.
Currently, only React frontends are supported.
Interested in integrating xChain Accounts? Consider filling in a quick survey.
This monorepo contains:
- Logic Sig - LogicSig that verifies ECDSA (secp256k1) signatures from EVM addresses
- SDK - TypeScript SDK for integrating EVM wallet signing with Algorand
- use-wallet - @txnlab/use-wallet with xChain EVM / MetaMask support
- use-wallet-ui - @txnlab/use-wallet-ui with xChain EVM / MetaMask support
- frontend - React demo application with MetaMask integration
- portal - Docs and information portal (TanStack Start + Cloudflare)
- rpc-server - Mock Ethereum JSON-RPC server (Cloudflare Worker) that lets MetaMask Mobile connect to Algorand as a custom network. Responds to standard RPC methods (
eth_chainId,eth_blockNumber,net_version,eth_gasPrice,eth_getBlockByNumber) and serves real ALGO balances viaeth_getBalanceby deriving the xChain EVM address and querying Algorand mainnet, converting from 6-decimal microAlgos to 18-decimal wei. - dfx - Deferred Execution Service (Cloudflare Worker + Durable Object) that accepts signed transaction groups, simulates them, and retries those that fail due to insufficient balance until they become valid or expire.
- Derive Algorand Address: Each EVM address (20 bytes) maps deterministically to a unique Algorand LogicSig address
- Sign with EVM Wallet: MetaMask signs the transaction/group ID using EIP-712 typed structured data (
eth_signTypedData_v4) - Verify on Algorand: The LogicSig recovers the public key from the signature and verifies it matches the template owner
- Execute Transaction: If verification succeeds, the transaction is approved
The LogicSig contract:
- Uses
ecdsaPkRecover(secp256k1) to recover the signer's public key - Derives the Ethereum address from the recovered public key (last 20 bytes of keccak256)
- Compares the recovered address against the template owner
- Computes an EIP-712 digest over the transaction ID (single txn) or group ID (atomic groups), providing domain separation
The LogicSig uses EIP-712 typed structured data rather than raw personal_sign for two reasons:
- Domain separation: The EIP-712 domain (
name,version) is embedded in the signed digest, preventing signatures from being replayed across different applications or protocols. Network-level replay protection is provided by the Algorand transaction's genesis hash, which is already part of the signed transaction ID/group ID. - Human-readable signing prompts: EVM wallets (MetaMask, etc.) display the structured fields to the user instead of an opaque hex blob, making it clear what is being authorized.
- Node.js 22+
- AlgoKit CLI 2.5+
- Docker (for LocalNet)
- pnpm >= 10.29.3
The recommended way to install pnpm is via Corepack, which ships with Node.js:
corepack enable
corepack prepare pnpm@10.29.3 --activateAlternative: standalone install
npm install -g pnpm@10.29.3
# Clone the repository
git clone https://github.com/algorandfoundation/xchain-accounts.git
cd xchain-accounts
# fetch the submodules (use-wallet, use-wallet-ui)
git submodule update --init --recursive
# Install dependencies
# Read the output carefully, you may need to approve build scripts.
pnpm i
# Start LocalNet
algokit localnet start
# Build all projects
algokit project run build# Start the frontend (from root directory)
cd projects/frontend
pnpm devOpen http://localhost:5173 and connect MetaMask to see EVM-controlled Algorand accounts in action.
Note: The derived Algorand address must be funded before it can send transactions. New accounts need a minimum balance of 0.1 ALGO to exist on the network. You can fund the account from AlgoKit LocalNet dispenser or use the frontend to display the address and send funds to it.
xchain-accounts/
├── projects/
│ ├── evm-logicsig/ # Smart contract (Algorand TypeScript)
│ ├── evm-sdk/ # TypeScript SDK
│ ├── frontend/ # React demo application
│ ├── portal/ # Docs/info portal (TanStack Start + Cloudflare)
│ ├── rpc-server/ # Mock Ethereum JSON-RPC (Cloudflare Worker)
│ ├── dfx/ # Deferred Execution Service (Cloudflare Worker + DO)
│ ├── use-wallet/ # Enhanced @txnlab/use-wallet with xChain EVM support
│ └── use-wallet-ui/ # Enhanced @txnlab/use-wallet-ui with xChain EVM support
Install the SDK:
npm install algo-x-evm-sdk
# or
pnpm add algo-x-evm-sdkBasic usage:
import { AlgoXEvmSdk } from 'algo-x-evm-sdk'
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
// Initialize
const algorand = AlgorandClient.fromEnvironment()
const sdk = new AlgoXEvmSdk({ algorand })
// Get Algorand address for an EVM address
const algoAddress = await sdk.getAddress({
evmAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2'
})
// Get a transaction signer (EIP-712 typed data signing)
const evmAddress = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2'
const { addr, signer } = await sdk.getSigner({
evmAddress,
signMessage: async ({ domain, types, primaryType, message }) => {
const data = JSON.stringify({ domain, types, primaryType, message })
return window.ethereum.request({
method: 'eth_signTypedData_v4',
params: [evmAddress, data]
})
}
})
// Use with algokit-utils
await algorand.send.payment({
sender: addr,
signer: signer,
receiver: recipientAddress,
amount: (1).algos()
})The use-wallet fork introduces a base class for xChain Accounts, as well as an implementation for Metamask. This should be a drop-in replacement for Algorand dApps.
Opinionated fork of use-wallet-ui adds "meta-wallet" functionality to dApps:
- transaction transparency, see what you are signing before you sign
- security context: runs in dApp; vulnerable in malicious or compromised dApps
- Initiate transactions for managing assets, sending ALGO, etc
- WIP
- Onboarding guide for xChain Accounts with 0 ALGO balance
Integration Effort:
- Drop-in for transaction transparency
- Minor integration needed for wallet management (integrate )
Possible future work:
- Develop optional companion extension for dApp-independent txn verification
- Integrated bridging to bootstrap account w/ USDC without leaving dApp
algokit project run buildThis compiles, in order (per .algokit.toml):
- Logic sig to TEAL (
evm-logicsig) - TypeScript SDK (
evm-sdk) - Use-wallet packages (
use-wallet) - Use-wallet-ui package (
use-wallet-ui) - Portal (
portal) - Frontend (
frontend) - RPC server (
rpc-server)
dfx is not part of the algokit workspace build; build it directly with pnpm --filter dfx build.
cd projects/evm-logicsig
algokit project run testContributions are welcome! Please see individual project READMEs for specific development guidelines:
- The LogicSig verifies signatures using ECDSA secp256k1 curve
- A template variable (owner address) ensures each EVM address has a unique Algorand address
- Signatures are automatically normalized to lower-S form because the AVM only accepts lower-S signatures
- EIP-712 domain separation prevents AVM<>EVM contamination
- The contract binds signatures to specific transaction/group IDs, preventing replay across AVM networks (genesisHash) & time (first/lastRound)
- Always verify the derived Algorand address matches expectations
GitHub Actions workflows are present in .github/workflows but are currently disabled (each file is suffixed .disabled). No automated testing, linting, or deployment runs on push at this time. The disabled workflows cover smart-contract CI/CD, validation, and release; re-enable by removing the .disabled suffix once the project is ready for automated pipelines.
MIT