Why This Tutorial Exists
Cross-chain agent development has a reputation for being hard. And historically, it was. You'd need to maintain RPC connections across chains, handle independent nonce tracking, write your own coordination layer, and debug failures that only happened in production on the one chain you hadn't tested.
Valence changes that by providing the orchestration layer as a service. You write the agent logic. Valence handles chain connectivity, state synchronization, trigger evaluation, and coordination. The result is an agent that runs cross-chain in hours, not weeks.
By the end of this tutorial, you'll have a working arbitrage agent running across Ethereum and Arbitrum on Valence's testnet. The same pattern scales to 6 chains and arbitrary complexity.
Prerequisites
Before you start, make sure you have:
- A Valence account (free at valence-7w4z.polsia.app/dashboard)
- Node.js 18+ and npm installed
- A basic understanding of DeFi mechanics (swaps, LP, bridge concepts)
- Testnet ETH on Ethereum Sepolia and Arbitrum Sepolia (faucets available in the dashboard)
You don't need Solidity or Rust. Valence abstracts chain-specific mechanics. If you can write JavaScript, you can build cross-chain agents.
Step 1: Install the SDK and Initialize Your Agent
The Valence JavaScript SDK is the fastest way to get started. Install it from npm, then initialize a client with your API key.
# Install the Valence SDK npm install @valence/sdk # Initialize your agent project mkdir my-cross-chain-agent && cd my-cross-chain-agent node -e "const { Valence } = require('@valence/sdk'); const v = new Valence({ apiKey: 'your-api-key' }); console.log('Connected to', v.chains.length, 'chains');"
Your API key is available in the Valence dashboard under Settings → API Keys. The SDK authenticates automatically and maps your account's connected chains.
const { Valence } = require('@valence/sdk'); const valence = new Valence({ apiKey: process.env.VALENCE_API_KEY, }); // List all chains available to your account const chains = valence.chains.list(); console.log("Available chains:", chains); // The full list on testnet includes: // ethereum, arbitrum, base, avalanche, solana, chromia
Step 2: Define Your Agent Strategy
Agents on Valence are defined by a configuration object — not a running process you monitor manually. You describe what the agent should do, how it should monitor conditions, and what actions to take. Valence handles the rest.
For this tutorial, we'll build a simple arbitrage agent. The strategy: watch the ETH/USDC price on Ethereum and Arbitrum. When the spread exceeds 0.5%, buy on the cheaper chain and sell on the expensive one.
const agent = { name: "eth-arb-agent-v1", chains: ["ethereum", "arbitrum"], // The agent's core logic: called on every evaluation tick evaluate: async (ctx) => { const { prices, balances } = ctx.state; // Get current ETH/USDC price on each chain const ethPrice = prices.get("ethereum", "ETH"); const arbPrice = prices.get("arbitrum", "ETH"); const spread = Math.abs(arbPrice - ethPrice) / ethPrice; // Only act if spread exceeds 0.5% if (spread < 0.005) return { action: "wait" }; // Determine direction: buy on cheaper, sell on expensive const buyChain = ethPrice < arbPrice ? "ethereum" : "arbitrum"; const sellChain = ethPrice < arbPrice ? "arbitrum" : "ethereum"; // Execute cross-chain arbitrage sequence return { action: "arbitrage", buyChain, sellChain, buyAsset: "ETH", sellAsset: "ETH", amount: balances.min(buyChain, "USDC", 100), // use up to $100 of USDC maxSlippage: 0.01, // 1% max slippage tolerance }; }, // Gas budget: prevent agents from spending more than configured gasBudget: { maxFeePerGas: 50, // gwei — skip execution if fees too high maxPriorityFeePerGas: 2, }, };
The agent's evaluate function is called on a schedule — you configure the frequency when you register the agent. The context object (ctx) provides real-time state: prices, balances, gas costs. The function returns either { action: "wait" } (do nothing) or an action object (execute the arbitrage).
Step 3: Register Triggers and Deploy
Triggers are the event conditions that fire your agent's execution cycle. Valence supports price triggers, balance triggers, time-based schedules, and cross-chain ratio conditions. You can combine multiple triggers on a single agent.
// Create the trigger const trigger = await valence.triggers.create({ name: "eth-arb-price-spread", type: "price_spread", chains: ["ethereum", "arbitrum"], asset: "ETH", quote: "USDC", threshold: 0.005, // fire when spread exceeds 0.5% evaluationInterval: 30, // check every 30 seconds }); // Register the agent with the trigger const deployedAgent = await valence.agents.deploy({ ...agent, triggerId: trigger.id, }); console.log("Agent deployed: ", deployedAgent.id); // → Agent deployed: agent_8f3a21b9
Once deployed, the agent runs autonomously. Valence evaluates the trigger condition every 30 seconds. When the spread exceeds 0.5%, the agent's evaluate function fires, and Valence coordinates the execution across both chains.
When a trigger fires: (1) Valence evaluates your evaluate() function. (2) If it returns an action, Valence checks gas budgets and compliance. (3) The action is dispatched to sub-agents on each chain. (4) Execution state is published to your dashboard in real time.
Step 4: Connect Wallets
Agents need wallets to execute transactions. You connect one wallet per chain through Valence's wallet module. Each wallet is independent — separate nonces, separate gas management, same owner key.
// Add a wallet for each chain the agent needs const ethWallet = await valence.wallets.connect({ chain: "ethereum", address: "0xYourEthereumWallet", label: "primary-eth", }); const arbWallet = await valence.wallets.connect({ chain: "arbitrum", address: "0xYourArbitrumWallet", label: "primary-arb", }); // Link wallets to the agent await valence.agents.linkWallets(deployedAgent.id, [ethWallet.id, arbWallet.id]);
Wallet management is non-custodial. Valence never holds your keys. Wallets are connected via signed messages, not exported. You can revoke access at any time from the dashboard.
Step 5: Monitor and Debug
Once your agent is running, real-time execution data is visible in the Valence dashboard. Every cycle logs trigger evaluations, action decisions, transaction hashes, and gas spent. You can filter by chain, status, or time range.
For programmatic access, the SDK provides a streaming event interface:
// Stream agent execution events in real time const stream = valence.agents.streamEvents(deployedAgent.id); stream.on("cycle", (event) => { console.log("Evaluation cycle:", event.timestamp); console.log(" ETH price (ETH):", event.prices.ethereum); console.log(" ETH price (ARB):", event.prices.arbitrum); console.log(" Action:", event.action); }); stream.on("transaction", (tx) => { console.log("Tx submitted:", tx.hash, "on", tx.chain); }); stream.on("error", (err) => { console.error("Execution error:", err.message, "on", err.chain); });
Common Pitfalls
Cross-chain execution has failure modes that don't exist in single-chain development. Here's what to watch for:
evaluate() function.What's Next
This tutorial walked through a simple arbitrage agent, but the same pattern applies to any cross-chain strategy: portfolio rebalancing, compliance monitoring, yield optimization, market making. The difference is in the agent logic, not the infrastructure.
To go further: explore multi-chain triggers (evaluating conditions across all 6 testnet chains), compliance layer integration (entity-level position limits enforced by the coordination engine), and the coordination processor for coordinating actions across agents running in parallel.
Start Building
Your first cross-chain agent is one API key away. SDK docs, live testnet, and working examples are in the Valence dashboard.