universal-algo-intent-kit
v0.1.1
Published
Cross-chain intent SDK: EVM (Somnia/Ethereum) → Algorand settlement
Maintainers
Readme
universal-algo-kit
Universal Algo Kit (UAK) is a TypeScript SDK + CLI for cross-chain intents:
- Source chain: EVM (Somnia / any Ethereum-compatible chain)
- Destination chain: Algorand (settlement via Algorand app calls)
It provides:
- An intent sender (EVM tx → emits intent events)
- An Algorand relayer (watches EVM events → settles corresponding Algorand app calls)
- A small CLI (
uak) for running the relayer and sending sample intents
This package is extracted from the working reference implementation in this repo (web3-hardhat-intent/) and is meant to be published as a standalone SDK.
Contents
- Install
- Architecture
- Transaction flow
- Architecture doc
- Quick start (SDK)
- Quick start (CLI)
- Configuration
- Supported intents
- API reference
- Troubleshooting
- Security model
- Deployment note
- Publishing (npm)
Install
npm i universal-algo-kitArchitecture
High-level components
flowchart LR
U["User (EVM wallet)"] -->|send tx| G["Gateway contract (EVM)"]
G -->|emit event IntentForwarded*| R["Relayer (off-chain)"]
R -->|app call| A["Algorand App (Counter/Todo)"]
R -->|optional routing| E["Algorand Executor App"]
E -->|inner app call| ARoles
- User: sends an EVM transaction that encodes the intent.
- Gateway (EVM): emits an event containing
user,target,nonce, and optional calldata bytes. - Relayer (off-chain): watches gateway events and performs Algorand settlement transactions.
- Algorand apps:
- Counter: direct settlement (no executor)
- Todo: settlement via Executor (for inner tx + authorization / nonce tracking pattern)
Transaction flow
1) EVM intent emission
The sender calls one of the gateway methods:
requestIntent(target, data)→ emitsIntentForwarded(...)forwardIntentWithData(target, data)→ emitsIntentForwardedWithData(..., data, ...)
UAK uses ethers to ABI-encode calldata for Counter/Todo intents and submits a normal EVM transaction.
2) Relayer event polling
The relayer:
- Polls EVM blocks (default
lookback=50,confirmations=3) - Reads gateway events in the safe range
- For each event:
- validates that
targetis allowed - maps
target(EVM address) →appId(Algorand) - converts
user(EVM address) into a 32-byte value used by Algorand apps - builds Algorand
appArgsmatching ARC4 method selectors expected by your Algorand apps
- validates that
3) Algorand settlement
There are two settlement paths:
Counter (direct app call)
The relayer calls the Counter Algorand app directly with an ARC4 selector:
increment()uint64ordecrement()uint64
Todo (via Executor)
The relayer calls the Executor app which performs an inner transaction to the Todo app:
- Build Todo inner args (
add_todo,toggle_todo,delete_todo) - Wrap them into Executor call args (
execute_with_data(...)) - Provide box references (relayer auth box, user nonce box, todo box) and include Todo app in
foreignApps
Fee note: Executor path sets a higher flat fee to cover inner transaction fees (currently 2000 microAlgos in the SDK).
Architecture doc
More detailed notes live in:
sdk/universal-algo-kit/docs/ARCHITECTURE.md
Quick start (SDK)
import { createUniversalAlgoKit } from "universal-algo-kit";
const uak = createUniversalAlgoKit({
evm: {
rpcUrl: process.env.SOMNIA_TESTNET_RPC_URL!,
gatewayAddress: process.env.ARC_GATEWAY_ADDRESS!,
privateKey: process.env.PRIVATE_KEY, // required to SEND intents
},
algorand: {
algodUrl: process.env.ALGORAND_ALGOD_URL!,
indexerUrl: process.env.ALGORAND_INDEXER_URL,
relayerMnemonic: process.env.ALGORAND_RELAYER_MNEMONIC!, // required to SETTLE intents
},
targets: {
counterAddress: process.env.COUNTER_ADDRESS,
todoAddress: process.env.TODO_ADDRESS,
},
appIds: {
counterAppId: Number(process.env.COUNTER_APP_ID),
todoAppId: Number(process.env.TODO_APP_ID),
executorAppId: Number(process.env.EXECUTOR_APP_ID),
},
relayer: {
pollIntervalMs: 5000,
confirmations: 3,
lookbackBlocks: 50,
maxRetries: 3,
},
});
// Send an intent on EVM (example: Counter.increment)
await uak.sender.sendCounterIncrement();
// Start the relayer loop to settle intents on Algorand
await uak.relayer.start();Quick start (CLI)
# Starts the relayer loop (reads .env in current dir)
npx uak relayerPoll once and exit:
npx uak relayer --onceSend example intents:
npx uak send-counter
npx uak send-todo-add --text "hello"
npx uak send-todo-toggle --id 1
npx uak send-todo-delete --id 1Configuration
UAK supports config via:
- explicit
createUniversalAlgoKit({...}) process.envvia the CLI (dotenvloaded automatically)
Required env vars
For sending intents (EVM):
SOMNIA_TESTNET_RPC_URL(orEVM_RPC_URL)ARC_GATEWAY_ADDRESSPRIVATE_KEY(sender)COUNTER_ADDRESSand/orTODO_ADDRESS
For relaying/settlement (Algorand):
ALGORAND_ALGOD_URLALGORAND_RELAYER_MNEMONICCOUNTER_APP_IDand/orTODO_APP_IDEXECUTOR_APP_ID(required if usingTODO_ADDRESS)
Recommended:
ALGORAND_INDEXER_URL
Optional relayer tuning
RELAYER_POLL_INTERVAL(ms, default5000)RELAYER_CONFIRMATIONS(default3)RELAYER_LOOKBACK_BLOCKS(default50)RELAYER_MAX_RETRIES(default3)
Supported intents
Counter
increment()decrement()
Todo
addTodo(string)toggleTodo(uint256)deleteTodo(uint256)
API reference
createUniversalAlgoKit(config)
Returns:
sender:EvmIntentSenderrelayer:AlgorandIntentRelayer
EvmIntentSender
sendCounterIncrement()sendTodoAdd(text: string)sendTodoToggle(id: bigint)sendTodoDelete(id: bigint)
AlgorandIntentRelayer
init()(called bystart())start()(infinite loop)pollOnce()(one polling iteration)
Troubleshooting
403 ... Two-factor authentication ... is required to publish packages
Your npm account/org requires 2FA for publishing. Publish with OTP or use a granular token with “bypass 2FA for publishing”.
Relayer starts but never sees events
- Ensure
SOMNIA_TESTNET_RPC_URLpoints to the correct chain - Ensure
ARC_GATEWAY_ADDRESSis the deployed gateway on that chain - Increase
RELAYER_LOOKBACK_BLOCKStemporarily if events are older than the default lookback
Algorand tx fails (logic eval / missing boxes)
- Confirm
COUNTER_APP_ID,TODO_APP_ID,EXECUTOR_APP_IDmatch the deployed apps - Ensure the Executor app is funded (box storage + fees)
- Ensure the relayer account is authorized in the Executor app (your app logic)
Security model
This SDK is a reference implementation and should be treated as such.
Key assumptions:
- The relayer is trusted to submit settlement transactions.
- The relayer only settles intents to configured/allowed targets.
Hardening checklist for production:
- Persist intent processing state (avoid duplicates across relayer restarts)
- Add stronger replay protection (read and verify nonce state from chain, not in-memory)
- Add allowlist/denylist rules per target and per method selector
- Add structured logging + monitoring + alerting
Deployment note
This SDK focuses on intent sending + relaying. Contract/app deployment is still handled by the reference projects in this repo:
- EVM contracts + gateway:
web3-hardhat-intent/ - Algorand apps (Counter/Todo/Executor):
executor/
Publishing (npm)
From sdk/universal-algo-kit/:
npm run build
npm publish --access publicBefore publishing, update:
sdk/universal-algo-kit/package.json(name,version,repository.url,author)
