# Brand Kit Source: https://docs.caldera.xyz/brand ## Logo Caldera Logosmarks in various colors ### Logo Wordmark Caldera Logosmarks in various colors ### Vertical Logo Wordmark Caldera Logosmarks in various colors ### Grayscale When brand colors don't suit your materials or technical constraints exist, use grayscale or black/white versions. Never use unauthorized color variations. Caldera Logosmarks in various colors ### Logo Don'ts: * Don't stretch or distort the logo * Don't use on backgrounds that compete for attention * Don't recreate or modify the logo * Don't use colors outside the approved palette ## Colors Vivid Orange Vivid Orange Vivid Orange Vivid Orange Vivid Orange ## Typography Descriptive alt text **PP Neue Corp Compact** is used for titles and headings in our marketing materials. The **Ultrabold** is the only font weight we use with the **Alternative l** and **Rounded Dots** options turned on. Descriptive alt text **KMR Apparat** is used for body and other supporting text on our marketing materials and is also the primary font used on most of our products. ## Useful Links [Download Assets](https://drive.google.com/drive/folders/1REtrZNumH40Ih-yzFy19ZuhZ6YI3CnvK?usp=drive_link) [Figma](https://www.figma.com/design/wjLpJ2ddxyO2xB4EV5b4Ea/-Ext.--Caldera---Brand-Guidelines---Assets---External?m=auto\&t=DHZiIWqg2E7iXot8-6) # What is Metalayer Source: https://docs.caldera.xyz/index Metalayer is Caldera's comprehensive interoperability solution that transforms fragmented blockchain networks into a unified Internet of Chains. Built specifically for the rollup-centric future, Metalayer provides the infrastructure needed to move value and execute actions seamlessly across multiple networks. ## The Challenge The multi-rollup ecosystem faces critical fragmentation: * **Complex bridging experiences** with multiple providers, varying security models, and confusing UX * **Asset isolation** where tokens remain trapped on their origin chains * **Developer overhead** requiring integration with numerous point solutions * **Liquidity fragmentation** across hundreds of separate networks ## The Solution Metalayer solves these challenges through two core solutions: ### Bridge Aggregation A unified interface that aggregates quotes from native bridges, intent-based protocols, and specialized providers to find optimal routes for any cross-chain transfer. ### Omnichain Tokens (Metatoken) A new standard enabling tokens to exist natively across multiple chains with unified supply and the same contract address everywhere. ## Why Metalayer? ### vs Point Solutions Rather than integrating with multiple bridge APIs that may become obsolete, Metalayer provides **future-proof infrastructure** that incorporates new bridge technologies and optimizations as they emerge. One integration gives you access to the entire ecosystem of cross-chain solutions. ### vs Other Aggregators **Ecosystem Integration**: Unlike generic aggregators, Metalayer is deeply integrated with the Caldera rollup ecosystem, providing **day-zero connectivity** for every new rollup launch and shared liquidity across 50+ connected networks. ### Network Effects Every integration strengthens the entire network: * **Shared Liquidity**: Aggregated demand across all Metalayer-connected applications * **Competitive Solver Markets**: More integrations attract more solvers, improving pricing and speed * **Unified Developer Experience**: Consistent APIs and tools across the entire rollup ecosystem ### Developer Benefits * **Single Integration**: One SDK replaces dozens of bridge-specific integrations * **Automatic Updates**: New bridge providers and optimizations added without code changes * **Unified Interface**: Consistent experience regardless of underlying bridge technology * **Proven Infrastructure**: Built on battle-tested Hyperlane messaging with custom security enhancements ## Simple Integration Get started with just a few lines of code: ```typescript theme={null} import { MetalayerClient } from '@metalayer/sdk'; const client = MetalayerClient.init({ apiKey: 'your-api-key-here', environment: 'mainnet', }); // Quote from Arbitrum to ApeChain const quoteData = await client.quote({ sourceChainId: 42161, sourceTokenAddress: '0x0000000000000000000000000000000000000000', destinationChainId: 33139, destinationTokenAddress: '0x0000000000000000000000000000000000000000', amount: BigInt('1000000000'), senderAddress: '0xYourAddress', }); ``` ## How It Works Metalayer operates as a three-layer architecture: 1. **Execution Layer**: Aggregates quotes and routes transactions optimally 2. **Solver Ecosystem**: Network of specialized entities that fulfill cross-chain requests 3. **Settlement Layer**: Secure messaging backbone built on Hyperlane for final settlement Learn more about [how Metalayer works](/metalayer/how-it-works/architecture) in our technical deep-dive. ## Explore Solutions Unified cross-chain transfers with optimal routing Universal token portability across networks ## Get Started Add cross-chain functionality to your app Embed a complete bridge interface Learn about the technical architecture View router locations and chain IDs # Metalayer System Architecture Source: https://docs.caldera.xyz/metalayer/how-it-works/architecture Three-layer system enabling secure cross-chain interoperability via bridge aggregation Metalayer is designed as a vertically-integrated interoperability stack that connects rollups through a three-layer architecture. Each layer serves a specific purpose in enabling seamless cross-chain interactions. ## Three-Layer System ### 1. Execution Layer The top layer handles bridge requests and routing decisions: * **Request Processing**: Parses user requirements and translates them into executable plans * **Quote Aggregation**: Simultaneously queries multiple bridge providers and execution engines * **Route Optimization**: Evaluates options based on cost, speed, security, and liquidity * **Transaction Assembly**: Constructs ready-to-sign transactions with optimal routing * **Status Tracking**: Monitors execution across all integrated providers ### 2. Bridge Provider Ecosystem The middle layer consists of different types of bridge providers that fulfill cross-chain requests: #### Intent-Based Networks * **Eco Solver (Caldera)**: ETH and native token focused routes #### Intent-Based Networks (External) * **Across Protocol**: Independent intent-based protocol with UMA verification * **Relay Protocol**: Independent cross-chain infrastructure with Solana support * **Eco Solver (Eco)**: Stablecoin-focused routes #### Native Bridges * **Arbitrum Bridge**: Direct L2 canonical bridge integration * **Optimism Bridge**: OP Stack canonical bridge access * **Base Bridge**: Native L2 bridge integration * **zkSync Bridge**: Zero-knowledge proof based bridge #### Specialized Bridge Providers * **MetaToken**: Caldera's omnichain token standard with hub-spoke architecture * **OFT**: LayerZero's omnichain token standard * **Future Integrations**: Expanding ecosystem of bridge technologies ### 3. Settlement Layer (Metalayer-Powered Routes only) The bottom layer provides secure messaging and final settlement: * **Hyperlane Integration**: Sovereign deployment of proven messaging technology * **Custom Validators**: Independent validator set for enhanced security * **Message Verification**: Cryptographic proofs ensure secure delivery * **Cross-Chain Reads**: Query state from multiple chains atomically * **Configurable Security**: Choose between fast finality and full finalization ## Data Flow Data Flow Infographic ## Component Interactions ### Bridge Request Flow 1. **User Submits Request**: Via SDK, widget, or direct API call 2. **Quote Aggregation**: System queries all available bridge providers 3. **Route Optimization**: Evaluates quotes by multiple criteria 4. **Execution Selection**: User or system selects optimal route 5. **Transaction Signing**: User signs constructed transaction 6. **Cross-Chain Execution**: Provider fulfills request on destination (via competitive solvers for intent-based routes, directly for native bridges) 7. **Settlement Verification**: * External intent protocols: Handle their own settlement * Metalayer-powered routes: Metalayer verifies and settles execution * Native bridges: Handle their own settlement ### Message Passing Flow (Metalayer-Powered Routes only) 1. **Message Dispatch**: Contract calls MetalayerRouter on source chain 2. **Event Emission**: Router emits cross-chain message event 3. **Validator Pickup**: Hyperlane validators detect and verify event 4. **Cross-Chain Relay**: Validators relay message to destination chain 5. **Delivery Execution**: Destination router executes message payload 6. **Confirmation**: Source chain receives confirmation of delivery ## Security Architecture ### Multi-Layer Security * **Execution Layer**: Rate limiting, quote validation, route sanity checks * **Provider Layer**: Liquidity commitments, reputation tracking, and route-level safeguards * **Settlement Layer**: Cryptographic proofs, validator consensus, finality guarantees ### Configurable Trust Models * **Fast Finality**: \~10 second latency with sequencer trust assumptions * **Full Finalization**: Wait for L2 finality with maximum security * **Custom Security**: Per-application security parameter configuration ### Economic Security * **Provider Liquidity**: Intent-based providers deploy their own capital and maintain balances across chains * **Validator Incentives**: Validators rewarded for honest behavior * **Risk Controls**: Route-level limits and monitoring mitigate malicious actions ## Deployment Architecture ### Per-Chain Deployments Each supported chain has consistent contract deployments: * **MetalayerRouter**: Main entry point for cross-chain operations * **Inbox Contracts**: Receive and process incoming messages * **IntentSource**: Registry for user intents and execution tracking (for Metalayer-Powered intents) * **MetaProver**: Generates proofs for intent fulfillment (for Metalayer-Powered intents) ### Shared Infrastructure * **Aggregation API**: Centralized service for quote aggregation, event indexing, and status tracking * **Eco Solver Networks**: * Caldera-operated solver for ETH and native token routes * Eco-operated solver for stablecoin-focused routes * **Validator Network**: Independent Hyperlane validator set for secure message passing ## Scalability Design ### Horizontal Scaling * **Provider Competition**: Multiple entities can fulfill the same route types * **Chain Agnostic**: Add new chains without modifying existing deployments * **Provider Integration**: Easy onboarding of new bridge providers ### Performance Optimization * **Parallel Processing**: Simultaneous quote requests to all providers * **Caching**: Intelligent caching of quotes and chain state * **Routing Heuristics**: Preference scoring based on historical latency and fees (ML-driven routing is on the roadmap) ## Next Steps Learn about intent-based execution Security model and economic incentives Understand the messaging layer # Intent System Source: https://docs.caldera.xyz/metalayer/how-it-works/intent-system Declarative cross-chain execution powered by competitive solver markets Metalayer's bridge aggregation system routes cross-chain transfers through multiple execution paths, including intent-based protocols with competitive solver markets. While not all bridge requests are intents, intent-based execution provides the fastest and most efficient routes for many cross-chain transfers. ## Intent-Based vs Direct Bridge Routes When you make a bridge request via the Metalayer SDK, Widget, or API, the system may route your transaction through different types of providers: **Intent-Based Routes** (this page focuses on these): * **Across Protocol**: Independent intent-based protocol using UMA for verification and settlement * **Relay Protocol**: Independent intent-based protocol using direct rebalancing for settlement * **Eco Solver (Caldera)**: Metalayer-Powered solver focused on ETH and native tokens * **Eco Solver (Eco)**: Metalayer-Powered solver focused on stablecoin routes **Direct Bridge Routes**: * **Native Bridges**: Direct integration with L2 canonical bridges (Arbitrum, Optimism, etc.) * **Other Bridge Providers**: Direct protocols without solver competition All routes benefit from Metalayer's aggregation, quote optimization, and unified developer experience, but only intent-based routes use the competitive solver model described below. ## How Intents Work ### Declarative Execution Developers specify **what** they want to achieve (the intent) without needing to define **how** it should be executed across different chains. This abstraction reduces complexity and potential errors in cross-chain operations. ### Competitive Solver Model Intent-based protocols use a competitive solver ecosystem where multiple entities compete to fulfill user intents: * **Fast-Fill Networks**: Solvers use their own capital to instantly deliver assets on destination chains * **Competitive Fulfillment**: Multiple solvers compete on speed, cost, and reliability * **Risk Management**: Solvers temporarily take on cross-chain settlement risk * **Proof of Fulfillment**: Solvers must provide cryptographic proof of completion via MetaProver ### Settlement Mechanisms Different intent-based protocols use different settlement approaches: * **Across Protocol**: Uses UMA's optimistic verification system * **Relay Protocol**: Uses direct rebalancing mechanisms * **Eco Solver**: Uses Metalayer's intent system on supported networks, Hyperlane for all networks ## Intent Flow Example ``` User Intent: "I want 100 USDC on ApeChain, I have ETH on Arbitrum" 1. Intent Processing: - Parse user requirements - Identify source assets (ETH on Arbitrum) - Define destination requirements (100 USDC on ApeChain) 2. Quote Aggregation: - Query supported providers for optimal routes - See [Aggregated Bridges](/metalayer/resources/aggregated-bridges) for complete provider list 3. Route Selection: - Evaluate by speed, fees, and solver capacity constraints - Present optimal route to user (may be intent-based or native bridge) 4. Execution (Intent-based route): - User signs transaction, funds escrowed in Vault (Metalayer-Powered routes only) - Intent registered in IntentSource contract (Metalayer-Powered routes only) - Solver fulfills instantly on ApeChain using own capital 5. Settlement (Intent-based route): - External protocols (Across, Relay): Handle their own settlement mechanisms - Metalayer-Powered routes (Eco): - Solver's fulfillment logged in Inbox contract - MetaProver generates proof of fulfillment - Proof sent via Hyperlane to source chain - IntentSource marks intent as complete - Solver claims reimbursement from Vault ``` ## Security Model ### Intent Verification * **Cryptographic Commitments**: Intents are cryptographically signed and immutable * **Execution Guarantees**: System ensures intents are fulfilled as specified * **Proof of Fulfillment**: Solvers must provide cryptographic proof of completion ### Solver Network Security * **Capital Commitments**: Solvers deploy their own liquidity and maintain inventory across chains * **Route-Level Limits**: Caldera enforces per-route maximums and cooldowns to cap exposure * **Diverse Providers**: Multiple external partners (Across, Relay, Eco) can service the same intent type * **Operational Monitoring**: Real-time tracking of fill latency, rebalancing health, and fulfillment accuracy Additional mechanics such as solver slashing and shared staking pools are on the roadmap and will be announced separately. ## Integration For developers building on Metalayer, bridge requests (including intents) are expressed via the Metalayer SDK. The SDK aggregates across multiple providers and may route through intent-based protocols or direct bridges: ```typescript theme={null} import { MetalayerClient, OrderStatus } from '@metalayer/sdk'; const client = MetalayerClient.init({ apiKey: process.env.METALAYER_API_KEY!, environment: 'mainnet', }); // Discover supported routes dynamically const { chains } = await client.getSupportedChains(); const quoteResponse = await client.quote({ sourceChainId: 42161, // Arbitrum sourceTokenAddress: '0x0000000000000000000000000000000000000000', // ETH destinationChainId: 33139, // Apechain destinationTokenAddress: '0x0000000000000000000000000000000000000000', // ETH amount: BigInt('1000000000000000000'), // 1 ETH senderAddress: '0xYourWalletAddress', }); const bestRoute = quoteResponse.quotes[0]; const submittedTxs: string[] = []; for (const step of bestRoute.steps) { switch (step.action.case) { case 'transactionRequest': const txHash = await walletClient.sendTransaction(step.action.value); submittedTxs.push(txHash); break; case 'eip712Data': await walletClient.signTypedData(step.action.value); break; } } const { order } = await client.getOrder({ sourceTransactionHash: submittedTxs[0], sourceChainId: 42161, }); if (order.status === OrderStatus.FULFILLED) { console.log('Bridge order completed successfully'); } ``` The SDK abstracts quote aggregation, calldata assembly, and fulfillment tracking across both intent-based protocols and direct bridges, so you can focus on the user experience rather than managing multiple bridge integrations. ## Next Steps Learn about the underlying messaging infrastructure Start building with intents # Cross-Chain Messaging Source: https://docs.caldera.xyz/metalayer/how-it-works/message-passing Secure cross-chain messaging with Hyperlane and custom state reads Metalayer provides a secure message passing system built on a sovereign deployment of Hyperlane's battle-tested technology, automatically deployed on every Caldera chain. This independent validator network is operated specifically for the Metalayer ecosystem. Messages can optionally include cross-chain state reads from an arbitrary number of chains, enabling real-time data access across the network. **Important**: Developers must interact exclusively with Metalayer's router contracts to ensure messages are correctly routed within our network, rather than referencing any public Hyperlane contracts that may exist on-chain. Message Passing Infographic ## Core Concepts ### Chains Each blockchain network is identified by a unique chain number in the Metalayer protocol. This chain identifier is used when specifying the destination chain for cross-chain messages. ### Cross-Chain Operations Metalayer Messaging supports two types of cross-chain operations: * **Writes**: Send messages and execute functions across chains * **Reads**: Query data from contracts on other chains ### Message Components * **Destination Domain**: The target blockchain network * **Recipient Address**: The contract address that will receive the message * **Read Operations**: Optional queries to execute on other chains * **Write Call Data**: The function call to execute on the destination chain * **Finality Flag**: Whether to wait for source chain finality before relay ## Configurable Finality Messages in Metalayer support two finality modes, allowing developers to balance speed and security: ### Soft Finality (Default) * **\~10 second latency** * Validators confirm sequencer commitment to include transaction * Optimal for most applications needing quick settlement * Trust assumption: Validators honestly report sequencer feed data ### Finalized Mode * Requires batch submission to parent chain and finality on that chain * Provides protection against sequencer reorgs * Note: Optimistic rollups retain 7-day dispute window * Same validator trust model as soft finality, but with additional reorg protection * **Recommended for high-value transfers or security-critical applications** ## System Architecture ### Component Architecture The diagram below shows the main components of the Metalayer system and how they interact: Component Architecture Infographic ### Message Flow The sequence diagram below illustrates the step-by-step process of sending a cross-chain message: Cross-Chain Messaging Infographic ## Gas Abstraction Metalayer handles cross-chain gas payments, allowing developers to pay for destination chain execution using the source chain's native token. This simplifies the user experience by eliminating the need to hold gas tokens on multiple chains. ## Security Features ### Message Verification * **Cryptographic Proofs**: All messages verified through Hyperlane's security model * **Independent Validators**: Sovereign validator set for enhanced security * **Configurable Thresholds**: Adjust security requirements per message type ### Cross-Chain State Reads * **Real-Time Data**: Query contract state from multiple chains simultaneously * **Atomic Operations**: Read results are included in message delivery * **Consistency Guarantees**: Reads are executed at a consistent block height ## Settlement Components ### Core Contracts * **MetalayerRouter**: Main entry point for dispatching cross-chain messages * **Inbox Contract**: Logs fulfillment actions on destination chains * **IntentSource**: Registry for user intents and execution tracking on source chains * **MetaProver**: Service that generates cryptographic proofs of fulfillment ### Settlement Flow 1. **Message Dispatch**: Application calls MetalayerRouter to send cross-chain message 2. **Event Emission**: Router emits message event picked up by validator network 3. **Cross-Chain Relay**: Validators transport message to destination chain 4. **Execution Logging**: Action logged in destination's Inbox contract 5. **Proof Generation**: MetaProver constructs proof of fulfillment message 6. **Settlement Verification**: Proof sent back to source chain for final settlement ## Future Evolution As rollup stacks evolve to support stack-native interoperability (like Superchain or ZKSync native bridging), Metalayer will automatically upgrade to use these mechanisms. Applications specifying "finalized" mode will seamlessly benefit from improved security guarantees without any code changes. Finalized mode brings the future benefits of stack-native interop to developers today — without forcing devs to lock into a specific ecosystem. ## Integration Examples ### Basic Message Sending ```solidity theme={null} import {IMetalayerRouter, ReadOperation} from "@metalayer/contracts/interfaces/IMetalayerRouter.sol"; import {FinalityState} from "@metalayer/contracts/lib/MetalayerMessage.sol"; IMetalayerRouter router = IMetalayerRouter(0x09Ce71C24ee2098e351c0cF2dC6431b414d247f3); // Apechain router address receiver = 0x1234567890123456789012345678901234567890; ReadOperation[] memory reads; bytes memory callData = abi.encodeWithSignature( "settle(bytes32,address,uint256)", intentId, receiver, amount ); uint256 fee = router.quoteDispatch( 33139, // destination domain receiver, reads, callData, FinalityState.INSTANT, 500_000 // destination gas limit ); router.dispatch{value: fee}( 33139, receiver, reads, callData, FinalityState.INSTANT, 500_000 ); ``` ### Cross-Chain Reads ```solidity theme={null} address recipientContract = 0x9876543210987654321098765432109876543210; ReadOperation[] memory reads = new ReadOperation[](2); reads[0] = ReadOperation({ domain: 1, target: 0x64FF4Fa53F2ae3f4dD0B3ad5A2ff2b0D6901b21f, callData: abi.encodeWithSignature("latestAnswer()") }); reads[1] = ReadOperation({ domain: 42161, target: 0xc778417E063141139Fce010982780140Aa0cD5Ab, callData: abi.encodeWithSignature("getReserves()") }); uint256 fee = router.quoteDispatch( 33139, recipientContract, reads, abi.encodeWithSignature("settle(bytes)" , readContext), FinalityState.FINALIZED, 600_000 ); router.dispatch{value: fee}( 33139, address(recipientContract), reads, abi.encodeWithSignature("settle(bytes)", readContext), FinalityState.FINALIZED, 600_000 ); ``` > **Reminder**: Router addresses and domain IDs are listed in [`/metalayer/resources/contract-deployments`](../resources/contract-deployments.mdx). Always quote the fee before dispatching so the router call includes the correct gas payment. ## Next Steps Full technical specification Learn about intent-based execution # Deploying MetaToken Hub Source: https://docs.caldera.xyz/metalayer/protocol/deploying-metatoken-hub Guide for self-service MetaToken hub deployment This guide covers the technical steps for deploying a MetaToken hub contract on your canonical token chain. The hub manages the canonical token supply and coordinates transfers to spoke chains. The MetaToken standard is open and permissionless, allowing anyone to deploy hub contracts using the proxy pattern for upgradeability. Deployment involves multi-chain coordination, domain configuration, and ongoing operational overhead including message monitoring, upgrades, and gas management. **We strongly recommend contacting Caldera for end-to-end production deployments.** See [Next Steps](#next-steps) below for more information. ## Source Code All MetaToken contracts are open source and available in the [metatoken-contracts](https://github.com/ConstellationCrypto/metatoken-contracts) repository. The contracts include comprehensive inline documentation. The hub implementation is located at [MetaERC20Hub.sol](https://github.com/ConstellationCrypto/metatoken-contracts/blob/main/src/token/MetaERC20Hub.sol). ## Deployment Architecture MetaToken hubs use the OpenZeppelin TransparentUpgradeableProxy pattern for upgradeability. The deployment consists of: 1. **TransparentUpgradeableProxy**: The proxy contract that users interact with 2. **ProxyAdmin**: Controls proxy upgrades, owned by your admin address 3. **MetaERC20Hub**: The implementation contract with hub logic The proxy pattern allows you to upgrade the implementation logic while maintaining the same contract address and escrowed token balances. ## Configuration Parameters You will need to provide the following initialization parameters for the MetaERC20Hub contract: | Parameter | Type | Description | | ------------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `metalayerDomain` | `uint32` | The Metalayer domain ID for the chain where the hub is deployed. This is typically the chain where your canonical token exists (e.g., 1 for Ethereum mainnet). See [contract deployments](/metalayer/resources/contract-deployments) for domain IDs. | | `metaERC20Version` | `uint8` | MetaToken protocol version. Currently `1`. Must match across all spokes to ensure message compatibility. | | `metalayerRouter` | `address` | The MetalayerRouter contract address on this chain. See [contract deployments](/metalayer/resources/contract-deployments). | | `canonicalToken` | `address` | The address of the canonical ERC20 token that will be locked in the hub. This is the native token that users deposit to mint on spoke chains. | | `tokenDecimals` | `uint8` | Token decimals of the canonical token. Must match the canonical token's decimals exactly. All spokes must also use this same decimal value. | | `ttlWindow` | `uint256` | Time-to-live window for transfer records in seconds. Must coordinate with spoke TTL settings. Typical values range from 1-7 days (86400-604800 seconds). | | `owner` | `address` | Admin address that receives `DEFAULT_ADMIN_ROLE`, `ADMIN_ROLE`, and `VALIDATOR_ROLE`. Should be a multisig or secure EOA. | ## Deployment Steps ### 1. Deploy the Proxy Deploy a TransparentUpgradeableProxy contract. The proxy will be the permanent address that manages the canonical token escrow. ```solidity theme={null} import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; // Deploy proxy with empty implementation initially TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( address(0), // initial implementation (can be address(0)) proxyAdminAddress, // ProxyAdmin contract address "" // empty initialization data ); ``` You'll also need a ProxyAdmin contract to manage upgrades: ```solidity theme={null} import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; ProxyAdmin proxyAdmin = new ProxyAdmin(ownerAddress); ``` ### 2. Deploy the Implementation Deploy the [MetaERC20Hub](https://github.com/ConstellationCrypto/metatoken-contracts/blob/main/src/token/MetaERC20Hub.sol) implementation contract. ```solidity theme={null} import {MetaERC20Hub} from "src/token/MetaERC20Hub.sol"; MetaERC20Hub implementation = new MetaERC20Hub(); ``` You will need all dependencies installed: * OpenZeppelin Contracts (Upgradeable) * Hyperlane Core Contracts ### 3. Point Proxy to Implementation Use the ProxyAdmin to upgrade the proxy to point to your MetaERC20Hub implementation and initialize it with the configuration parameters listed above. ```solidity theme={null} // Upgrade and initialize the proxy proxyAdmin.upgradeAndCall( ITransparentUpgradeableProxy(address(proxy)), address(implementation), initializationData ); ``` The hub is now deployed and initialized at the proxy address. ### 4. Configure the Hub After deploying your hub, you'll need to register spoke contracts as they are deployed. **Register spokes on hub:** Call `setDomainAddressBatch` on your MetaERC20Hub to register each spoke's address. ```solidity theme={null} hub.setDomainAddressBatch( [spokeChain1Domain, spokeChain2Domain], [spoke1Address.addressToBytes32(), spoke2Address.addressToBytes32()] ); ``` You can add spokes incrementally as you deploy them to additional chains. ### 5. Test the Deployment Approve the hub to spend your canonical tokens, then initiate a small test transfer from hub to a spoke: ```solidity theme={null} // Approve hub to lock canonical tokens IERC20(canonicalToken).approve(address(hub), amount); // Transfer to spoke hub.transferRemote{value: gasFee}( spokeDomain, recipientAddress.addressToBytes32(), smallAmount ); ``` Monitor the Hyperlane message delivery and verify the spoke mints the correct amount to the recipient. ## Next Steps After deploying your hub, you'll need to deploy spoke contracts on each chain where you want your token available. Self-deploying MetaToken hubs involves significant ongoing operational complexity. Caldera's managed MetaToken deployments provide: * **Deterministic Addressing**: Automated deployment tooling ensures consistent contract addresses across all chains * **Ongoing Operations**: Message monitoring, implementation upgrade coordination across all chains, and 24/7 incident response * **Gas & State Management**: Interchain Gas Paymaster funding, TTL pruning, and storage optimization * **Production Support**: Direct access to Caldera's infrastructure and protocol teams Contact for production MetaToken deployments Deploy spoke contracts on target chains # Deploying MetaToken Spoke Source: https://docs.caldera.xyz/metalayer/protocol/deploying-metatoken-spoke Guide for self-service MetaToken spoke deployment This guide covers the technical steps for deploying a MetaToken spoke contract on a supported chain. The MetaToken standard is open and permissionless, allowing anyone to deploy spoke contracts using the proxy pattern for upgradeability. **Prerequisites**: You must have a MetaToken hub already deployed on your canonical token chain. See the [Deploying MetaToken Hub](/metalayer/protocol/deploying-metatoken-hub) guide first if you haven't deployed a hub yet. Deployment involves multi-chain coordination, domain configuration, and ongoing operational overhead including message monitoring, upgrades, and gas management. **We strongly recommend contacting Caldera for end-to-end production deployments.** See [Next Steps](#next-steps) below for more information. ## Source Code All MetaToken contracts are open source and available in the [metatoken-contracts](https://github.com/ConstellationCrypto/metatoken-contracts) repository. The contracts include comprehensive inline documentation. The spoke implementation is located at [MetaERC20Spoke.sol](https://github.com/ConstellationCrypto/metatoken-contracts/blob/main/src/token/MetaERC20Spoke.sol). ## Deployment Architecture MetaToken spokes use the OpenZeppelin TransparentUpgradeableProxy pattern for upgradeability. The deployment consists of: 1. **TransparentUpgradeableProxy**: The proxy contract that users interact with 2. **ProxyAdmin**: Controls proxy upgrades, owned by your admin address 3. **MetaERC20Spoke**: The implementation contract with token logic The proxy pattern allows you to upgrade the implementation logic while maintaining the same contract address and token balances. ## Configuration Parameters You will need to provide the following initialization parameters for the MetaERC20Spoke contract: | Parameter | Type | Description | | ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `metalayerDomain` | `uint32` | The Metalayer domain ID for the chain you're deploying to. This is a unique identifier assigned to each chain in the Metalayer network (e.g., 33139 for Apechain, 56 for BSC). See [contract deployments](/metalayer/resources/contract-deployments) for domain IDs. | | `hubDomain` | `uint32` | The Metalayer domain ID where your MetaERC20Hub is deployed. This must match the hub's `localDomain` parameter. The hub routes high-value transfers and processes unlock requests back to the canonical chain. | | `metaERC20Version` | `uint8` | MetaToken protocol version. Currently `1`. Must match the hub's version to ensure message compatibility across all spokes. | | `metalayerRouter` | `address` | The MetalayerRouter contract address on this chain. See [contract deployments](/metalayer/resources/contract-deployments). | | `tokenName` | `string` | ERC20 token name (e.g., "My Token"). | | `tokenSymbol` | `string` | ERC20 token symbol (e.g., "MTK"). | | `tokenDecimals` | `uint8` | Token decimals. Must exactly match the hub's token decimals. Typically `18` for standard ERC20 tokens. | | `securityThreshold` | `uint256` | Amount (in token base units) above which transfers are routed through the hub for validator review instead of direct spoke-to-spoke. Setting to `0` forces all transfers through hub. Contact Caldera for recommendations based on your token's value and security model. | | `ttlWindow` | `uint256` | Time-to-live window for transfer records in seconds. Must coordinate with hub TTL settings to ensure transfers don't expire prematurely. Typical values range from 1-7 days (86400-604800 seconds). | | `owner` | `address` | Admin address that receives `DEFAULT_ADMIN_ROLE` and `ADMIN_ROLE`. Should be a multisig or secure EOA. | ## Deployment Steps ### 1. Deploy the Proxy Deploy a TransparentUpgradeableProxy contract. The proxy will be the permanent address that users interact with for the token. ```solidity theme={null} import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; // Deploy proxy with empty implementation initially TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( address(0), // initial implementation (can be address(0)) proxyAdminAddress, // ProxyAdmin contract address "" // empty initialization data ); ``` You'll also need a ProxyAdmin contract to manage upgrades: ```solidity theme={null} import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; ProxyAdmin proxyAdmin = new ProxyAdmin(ownerAddress); ``` ### 2. Deploy the Implementation Deploy the [MetaERC20Spoke](https://github.com/ConstellationCrypto/metatoken-contracts/blob/main/src/token/MetaERC20Spoke.sol) implementation contract. ```solidity theme={null} import {MetaERC20Spoke} from "src/token/MetaERC20Spoke.sol"; MetaERC20Spoke implementation = new MetaERC20Spoke(); ``` You will need all dependencies installed: * OpenZeppelin Contracts (Upgradeable) * Hyperlane Core Contracts ### 3. Point Proxy to Implementation Use the ProxyAdmin to upgrade the proxy to point to your MetaERC20Spoke implementation and initialize it with the configuration parameters listed above. ```solidity theme={null} // Upgrade and initialize the proxy proxyAdmin.upgradeAndCall( ITransparentUpgradeableProxy(address(proxy)), address(implementation), initializationData ); ``` The spoke is now deployed and initialized at the proxy address. ### 4. Configure the Spoke After deploying your spoke, configure domain mappings to enable cross-chain transfers. **Register spoke on hub:** Call `setDomainAddressBatch` on your MetaERC20Hub to register this spoke's address. ```solidity theme={null} hub.setDomainAddressBatch( [spokeDomain], [spokeAddress.addressToBytes32()] ); ``` **Register hub on spoke:** Call `setDomainAddressBatch` on your spoke to register the hub's address. ```solidity theme={null} spoke.setDomainAddressBatch( [hubDomain], [hubAddress.addressToBytes32()] ); ``` **Register other spokes (optional):** For direct spoke-to-spoke transfers, register each spoke's address on every other spoke contract. ### 5. Test the Deployment Initiate a small test transfer from hub to spoke: ```solidity theme={null} hub.transferRemote{value: gasFee}( spokeDomain, recipientAddress.addressToBytes32(), smallAmount ); ``` Monitor the Hyperlane message delivery and verify the spoke mints the correct amount to the recipient. ## Next Steps Self-deploying MetaToken spokes involves significant ongoing operational complexity. Caldera's managed MetaToken deployments provide: * **Deterministic Addressing**: Automated deployment tooling ensures consistent contract addresses across all chains * **Ongoing Operations**: Message monitoring, implementation upgrade coordination across all chains, and 24/7 incident response * **Gas & State Management**: Interchain Gas Paymaster funding, TTL pruning, and storage optimization * **Production Support**: Direct access to Caldera's infrastructure and protocol teams Contact for production MetaToken deployments Learn about MetaToken architecture # Metalayer Protocol Source: https://docs.caldera.xyz/metalayer/protocol/metalayer Core protocol specifications and architecture The Metalayer protocol is an upgradeable Hyperlane deployment operated by Caldera. It standardizes how intents (for intent-based routes), bridge operations, and arbitrary messages move between Metalayer-connected chains. This page documents the on-chain contracts and data structures developers interact with directly. ## Core Components * **MetalayerRouter** (`IMetalayerRouter`): primary entry point for dispatching and receiving cross-chain messages. Maintains the router registry for every Metalayer domain and forwards deliveries to application contracts. * **Metalayer ISMs**: three Interchain Security Module (ISM) variants are deployed per domain. `multisigIsm` validates instant finality messages, `multisigIsmFinalized` waits for L1 finality, and `espressoIsm` is reserved for the Espresso restaking integration. * **Interchain Gas Paymaster (IGP)**: default Hyperlane hook that collects source-chain gas payments and funds execution on the destination chain. * **MetalayerMessage library**: encodes message metadata, read operations, and finality flags. All router dispatches use this format. ## Domains & Contract Addresses Each supported blockchain is assigned a Metalayer domain ID. Router and ISM addresses are published in [`/metalayer/resources/contract-deployments`](../resources/contract-deployments.mdx). Applications should fetch addresses dynamically instead of inlining them. ## Dispatch Lifecycle 1. **Quote the fee** – call `quoteDispatch` with the destination domain, recipient, optional read operations, write calldata, desired `FinalityState`, and destination gas limit. The function returns the required source-chain payment. 2. **Dispatch** – call `dispatch` with the same parameters and send the quoted fee as `msg.value`. The router stores the Metalayer message, emits `MetalayerDispatch`, and enqueues the payload in the Hyperlane mailbox. 3. **Relay & Verification** – Metalayer validators relay the message. The destination router verifies the proof using the appropriate ISM (instant, finalized, or espresso) before invoking the recipient's `handle` function. 4. **Read Results** – if read operations were requested, the relayer includes their results in the delivery so the recipient contract can act on consistent cross-chain state. ```solidity theme={null} import {IMetalayerRouter, ReadOperation} from "@metalayer/contracts/interfaces/IMetalayerRouter.sol"; import {FinalityState} from "@metalayer/contracts/lib/MetalayerMessage.sol"; IMetalayerRouter router = IMetalayerRouter(routerAddress); ReadOperation[] memory reads; uint256 fee = router.quoteDispatch( destinationDomain, recipient, reads, callData, FinalityState.INSTANT, 500_000 ); router.dispatch{value: fee}( destinationDomain, recipient, reads, callData, FinalityState.INSTANT, 500_000 ); ``` ## Read Operations `ReadOperation` requests the relayer to execute static calls on other chains before the destination write executes: ```solidity theme={null} struct ReadOperation { uint32 domain; // chain domain to query address target; // contract to call bytes callData; // ABI-encoded function call } ``` The destination recipient receives the original array alongside `bytes[] readResults`, ensuring writes can make decisions with fresh, cross-chain state. ## Finality States `FinalityState` is encoded in every Metalayer message: * `INSTANT` – rely on rollup sequencer commitments (default, \~10s latency). * `FINALIZED` – wait for L1 finality and dispute windows before delivery. * `ESPRESSO` – reserved for the upcoming Espresso-integrated security tier. Select the finality tier that matches your protocol's risk tolerance. The same dispatch/quote functions are used for all tiers; only the enum differs. ## Roles & Governance `MetalayerRouter` uses `AccessControlDefaultAdminRulesUpgradeable` with the following roles: | Role | Purpose | | --------------------- | ----------------------------------------------------------------------- | | `DEFAULT_ADMIN_ROLE` | Owns upgrade and role management permissions. Held by Caldera multisig. | | `ISM_MANAGER_ROLE` | Updates ISM addresses or switches finality policies. | | `ROUTER_MANAGER_ROLE` | Manages the domain → router address mapping. | | `IGP_MANAGER_ROLE` | Sets or replaces the default interchain gas paymaster hook. | Applications never require these roles; integration is limited to dispatching messages and implementing the recipient interface. ## Key Events * `MetalayerDispatch(sender, destinationDomain, recipient, nonce)` – emitted for every outbound message; useful for off-chain indexing. * `RouterSet(chainId, router)` – recorded whenever a domain mapping changes. * `MetalayerIsmSet`, `MultisigIsmSet`, `EspressoIsmSet` – governance events for ISM upgrades. ## Upgrade Notes * Routers are deployed behind proxies and follow OpenZeppelin upgrade safety rules. Caldera publishes upgrade notices prior to any contract changes. * Downstream contracts should treat router addresses as immutable within a deployment epoch but always reference them via configuration, not constants, to accommodate upgrades or emergency rotations. * Gas payments and ISM configurations are chain-specific; fetch configuration from the SDK or JSON context files before submitting transactions. # MetaToken Source: https://docs.caldera.xyz/metalayer/protocol/metatoken MetaToken specifications and implementation details MetaToken is Caldera's omnichain token standard built on top of the Metalayer message-passing stack. It provides hub-and-spoke contracts that maintain a single canonical supply, deterministic addresses across every domain, and configurable security controls for high-value transfers. **Source Code**: All MetaToken contracts are open source and available at [metatoken-contracts](https://github.com/ConstellationCrypto/metatoken-contracts) with comprehensive inline documentation. ## Architecture Overview * **MetaERC20Hub** (canonical chain): Locks the native asset, tracks escrowed balances, and dispatches mint instructions to spokes. Receives `UnlockRequest` messages to release canonical tokens. Maintains a validator-reviewed buffer for high-value relays. * **MetaERC20Spoke** (remote chains): Mints and burns the synthetic representation of the token. Routes transfers either directly to another spoke or back through the hub depending on security thresholds. * **MetaERC20Base**: Shared logic that handles transfer bookkeeping, deterministic transfer IDs, domain registration, and dispatching through `IMetalayerRouter`. All contracts are upgradeable via `AccessControlDefaultAdminRulesUpgradeable` and inherit Metalayer's interchain security guarantees. ## Message Types MetaToken messages are encoded via `MetaERC20MessageStruct` and fall into one of four categories: | Type | Description | | --------------- | -------------------------------------------------------------------------------------------------------------- | | `MintRequest` | Spoke mints synthetic tokens to the recipient. Default for spoke-to-spoke transfers. | | `UnlockRequest` | Hub releases canonical tokens to the recipient after a spoke burn. | | `SecurityRelay` | Spoke-to-spoke transfer exceeding the configured threshold. Buffered on the hub for manual validator approval. | | `AdminAction` | Reserved for emergency reissue or administrative overrides. | Each message carries the transfer ID, timestamp, source token decimals, destination domain, recipient, and raw amount. Transfer IDs are deterministic hashes of sender, amount, and destination to guarantee uniqueness across the network. ## Transfer Flows ### Hub → Spoke 1. User deposits canonical tokens into the Hub (`MetaERC20Hub`). 2. Hub locks funds and emits a `MintRequest` to the destination spoke. 3. Spoke mints the synthetic supply to the recipient after converting decimals if necessary. ### Spoke → Hub 1. User calls `transferRemote` on the spoke with the hub domain and target recipient. 2. Spoke burns the synthetic tokens and emits an `UnlockRequest` to the hub. 3. Hub validates the request against locked balance and releases canonical tokens. ### Spoke → Spoke (Standard) 1. Spoke burns the source-chain synthetic tokens and generates a `MintRequest` for the destination spoke. 2. Destination spoke mints the requested amount to the recipient address. ### Spoke → Spoke (High Value) 1. If `amount >= securityThreshold`, the spoke emits a `SecurityRelay` targeting the hub instead of the destination spoke. 2. Hub buffers the transfer and emits `SecurityRelayBuffered` until an operator with `VALIDATOR_ROLE` reviews the request. 3. Upon approval, the hub re-dispatches the transfer as a `MintRequest` to the destination spoke. This layered approach lets token issuers tailor latency vs. security for different transfer sizes. ## On-Chain Integration Tokens expose a single entry point for user transfers: ```solidity theme={null} import {TypeCasts} from "@hyperlane-xyz/core/contracts/libs/TypeCasts.sol"; import {MetaERC20Spoke} from "@metalayer/contracts/token/MetaERC20Spoke.sol"; using TypeCasts for address; MetaERC20Spoke spoke = MetaERC20Spoke(0xYourToken); bytes32 transferId = spoke.transferRemote{ value: gasFee }( 33139, // recipient domain (Apechain) address(0xRecipient).addressToBytes32(), 1_000_000 * 10 ** spoke.decimals() // amount in local units ); ``` `transferRemote` internally: 1. Validates the destination domain and recipient. 2. Records the transfer for replay protection and TTL-based pruning. 3. Dispatches the encoded MetaERC20 message via `metalayerRouter.dispatch` using the spoke's configured finality state and gas limit. To determine the required `gasFee`, call the spoke's `quoteDispatchFee()` helper (available in the deployed package) or invoke `router.quoteDispatch` directly with the token's configured gas limit and finality state. ## Roles & Governance | Contract | Role | Purpose | | -------- | -------------------- | ----------------------------------------------------------- | | Hub | `DEFAULT_ADMIN_ROLE` | Owns upgrades and role assignment. | | Hub | `ADMIN_ROLE` | Manages domain mappings, gas limits, and TTL windows. | | Hub | `VALIDATOR_ROLE` | Approves or rejects buffered `SecurityRelay` transfers. | | Spoke | `DEFAULT_ADMIN_ROLE` | Owns upgrades and role assignment. | | Spoke | `ADMIN_ROLE` | Updates thresholds, domain mappings, and gas configuration. | Issuers typically maintain the admin roles while Caldera maintains the router roles. Validators can be rotated to expand or tighten manual review policies. ## Operational Controls * **TTL Window**: Transfers older than the configured TTL can be pruned to reclaim storage. * **Security Threshold**: Adjustable per spoke; setting to zero forces all transfers through the hub, while high values favour low-latency spoke-to-spoke routing. * **Gas Limits**: Each deployment specifies a max gas limit enforced when dispatching through the router to prevent runaway costs. * **Emergency Procedures**: Hub admins can perform `MetaERC20AdminUnlock` to release stuck funds; spoke admins can `MetaERC20AdminReissue` synthetic balances if a destination chain requires remediation. ## Deployment Information MetaToken deployments require both a hub contract (on your canonical token chain) and spoke contracts (on each destination chain): * For self-service deployment, see the [hub deployment guide](/metalayer/protocol/deploying-metatoken-hub) and [spoke deployment guide](/metalayer/protocol/deploying-metatoken-spoke). We strongly recommend using Caldera's managed deployments for production use cases. * Deterministic addresses and per-network configuration will be published alongside each rollout; reach out to Caldera for the latest deployment matrix. * All deployments share the same message format and can be upgraded without breaking deterministic transfer IDs, provided the storage layout gaps are respected. For architectural diagrams and example flows, refer back to the [Omnichain Tokens solution guide](/metalayer/solutions/omnichain-tokens). # Aggregated Bridges Source: https://docs.caldera.xyz/metalayer/resources/aggregated-bridges Bridge providers integrated into the Metalayer routing engine The Metalayer aggregator evaluates multiple bridge providers to surface the best route for each transfer. Use the tables below to understand which protocols are currently available in production builds. ## Metalayer | Bridge | Type | Description | Time | | ------------- | ------------------- | ---------------------------------------------------------------- | ------------ | | **MetaToken** | Multichain Standard | Caldera's token standard for seamless Metalayer interoperability | Near-instant | ## Native Bridges | Bridge | Type | Time | Website | | ------------------ | ------ | --------------------------------------- | ---------------------------------- | | **Arbitrum Nitro** | Native | 10-15 min deposits, 7 days withdrawals | [arbitrum.io](https://arbitrum.io) | | **OP Stack** | Native | 2-5 min deposits, 7 days withdrawals | [optimism.io](https://optimism.io) | | **zkSync** | Native | 10-20 min deposits, 4 hours withdrawals | [zksync.io](https://zksync.io) | ## Third-Party Bridges | Bridge | Type | Description | Website | | ----------------- | ------------------- | --------------------------------------------------------- | ---------------------------------------------- | | **Across** | Intents | Fast bridging with optimistic verification | [across.to](https://across.to) | | **Eco** | Intents | Specialized stablecoin infrastructure for emerging chains | [eco.org](https://eco.org) | | **Relay** | Intents | Cross-chain infrastructure including Solana support | [relay.link](https://relay.link) | | **LayerZero OFT** | Multichain Standard | LayerZero omnichain fungible token standard | [layerzero.network](https://layerzero.network) | Cross-architecture routes (e.g., Solana support via Relay) are in active development and will be documented once production ready. For widget implementation guidance, see [Bridge Aggregator](/metalayer/solutions/bridge-aggregator). # Audits Source: https://docs.caldera.xyz/metalayer/resources/audits Security audit reports for Metalayer protocols ## Completed Audits | Name | Auditor | Date | Report | | ------------------- | ------- | ------------- | -------------------------------------------------------------------------------------------------------- | | Metalayer Contracts | Halborn | July 15, 2025 | [View Report](https://www.halborn.com/audits/caldera/metalayer-contracts-cbaf11) | | MetaToken | Halborn | July 23, 2025 | [View Report](https://www.halborn.com/audits/caldera/metalayer-fetcher-smart-contract-assessment-7f40a4) | # Contract Deployments Source: https://docs.caldera.xyz/metalayer/resources/contract-deployments Metalayer router deployments on mainnet and testnet networks Metalayer's message passing protocol is deployed across multiple blockchain networks to enable seamless cross-chain communication. For technical details about the protocol architecture, see [Metalayer System Architecture](/metalayer/how-it-works/architecture). ## Mainnet Deployments | Name | Chain ID | Router Address | | :-------------- | :--------- | :------------------------------------------- | | Base | 8453 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | Apechain | 33139 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | Arbitrum One | 42161 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | Rari | 1380012617 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | Form Network | 478 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | AlienX | 10241024 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | Appchain | 466 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | Molten | 360 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | Sanko | 1996 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | Manta Pacific | 169 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | B3 | 8333 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | Ethereum | 1 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | | BNB Smart Chain | 56 | `0x09ce71c24ee2098e351c0cf2dc6431b414d247f3` | ## Testnet Deployments | Name | Chain ID | Router Address | | :-------------------------- | :------- | :------------------------------------------- | | TOY CHAIN Testnet | 21000000 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Ethereum Sepolia | 11155111 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Sanko Testnet | 1992 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Studio Chain Testnet | 616 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Base Sepolia | 84532 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Curtis | 33111 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Manta Sepolia | 3441006 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Towns Testnet | 6524490 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Binance Smart Chain Testnet | 97 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | B3 Testnet | 1993 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Arbitrum Sepolia | 421614 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Solo Testnet | 8884571 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Prime Chain Testnet | 2099 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Genlayer Testnet | 4221 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Intuition Testnet | 13579 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | | Mawari Testnet | 576 | `0x6f23b0211056035a22430a10fd27ded8547dc377` | # Widget Supported Chains Source: https://docs.caldera.xyz/metalayer/resources/widget-supported-chains Default chain availability in the Metalayer bridge widget The Metalayer bridge widget ships with a curated list of chains that are supported out of the box. The SDK keeps this dataset in sync; call `client.getSupportedChains()` to retrieve the latest information for your environment instead of hard-coding chain metadata. All Caldera-hosted chains are scheduled to land in the widget as they go live, so expect this table to expand alongside the Caldera ecosystem. ## Supported Networks ### Production Networks (Mainnets) #### L1 & Shared L2 Networks | Chain | Chain ID | Native Currency | | ------------------- | -------- | --------------- | | **Ethereum** | 1 | ETH | | **Arbitrum One** | 42161 | ETH | | **Base** | 8453 | ETH | | **BNB Smart Chain** | 56 | BNB | #### Caldera-Powered Rollups | Chain | Chain ID | Native Currency | | ----------------- | ---------- | --------------- | | **AlienX** | 10241024 | ETH | | **Apechain** | 33139 | APE | | **Appchain** | 466 | ETH | | **B3** | 8333 | ETH | | **Form Network** | 478 | ETH | | **Manta Pacific** | 169 | ETH | | **Molten** | 360 | MOLTEN | | **Rari** | 1380012617 | ETH | | **Sanko** | 1996 | DMT | ### Test Networks (Testnets) #### Public Testnets | Chain | Chain ID | Native Currency | | ------------------------------- | -------- | --------------- | | **Arbitrum Sepolia** | 421614 | ETH | | **Base Sepolia** | 84532 | ETH | | **Binance Smart Chain Testnet** | 97 | BNB | | **Ethereum Sepolia** | 11155111 | ETH | #### Caldera Testnets | Chain | Chain ID | Native Currency | | ------------------------ | -------- | --------------- | | **B3 Testnet** | 1993 | ETH | | **Curtis** | 33111 | APE | | **Intuition Testnet** | 13579 | tTRUST | | **Manta Sepolia** | 3441006 | ETH | | **Mawari Testnet** | 576 | MAWARI | | **Prime Chain Testnet** | 2099 | ETH | | **Sanko Testnet** | 1992 | tDMT | | **Solo Testnet** | 8884571 | ETH | | **Studio Chain Testnet** | 616 | KARRAT | | **TOY CHAIN Testnet** | 21000000 | TOY | | **Towns Testnet** | 6524490 | ETH | > **Tip**: For the authoritative list (including newly onboarded chains) call `client.getSupportedChains()`. ## Bridge Providers For the list of bridges aggregated by the widget, see [Aggregated Bridges](/metalayer/resources/aggregated-bridges). # API Reference Source: https://docs.caldera.xyz/metalayer/sdk/api-reference Type definitions and data structures for the Metalayer SDK # Core Types Complex data structures used throughout the Metalayer SDK for transaction execution, order tracking, and cross-chain operations. ## Chain Comprehensive blockchain network information including configuration and metadata. | Property | Type | Description | | ----------------- | --------------------------------------- | ------------------------------------------------------------------------ | | `identifier` | **[ChainIdentifier](#chainidentifier)** | Unique identifier for the blockchain network | | `name` | `string` | Human-readable name of the blockchain (e.g., "Ethereum", "Arbitrum One") | | `isTestnet` | `boolean` | Whether this is a testnet chain used for development and testing | | `imageUrl` | `string` | URL to the chain's logo or icon image | | `parentChain` | **[ChainIdentifier](#chainidentifier)** | Parent chain identifier with both ID and architecture | | `stack` | `RollupStack` | Stack used by this chain (Nitro, ZkSync, Optimism) | | `nativeCurrency` | `NativeCurrency` | Native currency information for this chain | | `defaultRpc` | `ChainRpc` | Default RPC for this chain | | `alternativeRpcs` | `ChainRpc[]` | Alternative RPCs for this chain | | `blockExplorer` | `ChainBlockExplorer` | Block explorer information for this chain | | `contracts` | `Record` | Known deployed contracts on this chain | | `lastUpdatedAt` | `Date` | Timestamp for when this chain was last updated | ## ChainIdentifier Minimal chain identifier containing ID and architecture information. | Property | Type | Description | | -------------- | ------------------------------------------- | ------------------------------------------------------ | | `id` | `number` | Unique numerical identifier for the blockchain network | | `architecture` | **[ChainArchitecture](#chainarchitecture)** | Blockchain architecture (Ethereum, Solana) | ## ExecutionStep A transaction execution step containing the specific action data for EVM transactions, EIP-712 signatures, or Solana transactions. | Property | Type | Description | | -------- | ----------------------------------------------- | ---------------------------------------------------- | | `action` | **[ExecutionStepAction](#executionstepaction)** | Union type containing the specific action to execute | ### ExecutionStepAction The `action` property is a union type with `case` and `value` properties: | Property | Type | Description | | -------- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | | `case` | `"transactionRequest"` \| `"eip712Data"` \| `"solanaTransaction"` | Discriminator indicating which type of action this is | | `value` | **[TransactionRequest](#transactionrequest)** \| **[EIP712Data](#eip712data)** \| **[SolanaTransaction](#solanatransaction)** | The actual action data based on the case | ### Action Types | Case | Value Type | Description | | ---------------------- | --------------------------------------------- | ------------------------------------------- | | `"transactionRequest"` | **[TransactionRequest](#transactionrequest)** | Standard EVM transactions | | `"eip712Data"` | **[EIP712Data](#eip712data)** | EIP-712 typed data for gasless transactions | | `"solanaTransaction"` | **[SolanaTransaction](#solanatransaction)** | Solana blockchain transactions | ```typescript theme={null} // Example: Processing ExecutionStep for (const step of quote.steps) { switch (step.action.case) { case 'transactionRequest': // Handle EVM transaction const txRequest = step.action.value; break; case 'eip712Data': // Handle EIP-712 signature const typedData = step.action.value; break; case 'solanaTransaction': // Handle Solana transaction const solanaTransaction = step.action.value; break; } } ``` ## TransactionRequest Standard EVM transaction request for on-chain operations. | Property | Type | Description | | --------- | ----------------- | ----------------------------------------------------------------- | | `to` | `string` | Target contract address | | `data` | `string` | Encoded function call data | | `value` | `string` | ETH value in wei | | `chainId` | `number` | Execution chain ID | | `type` | `TransactionType` | Transaction type (`ERC20_APPROVAL`, `CONTRACT_WRITE`, `TRANSFER`) | ## EIP712Data EIP-712 typed data structure for gasless transactions and meta-transactions. | Property | Type | Description | | ------------- | -------------------------------------- | ------------------------------------------------------- | | `account` | `string` | Account address that will sign this typed data | | `domain` | `EIP712Domain` | Domain separator information for signature verification | | `types` | `Record` | Type definitions for structured data | | `primaryType` | `string` | Primary type name being signed | | `message` | `object` | The structured data to be signed | ## SolanaTransaction Solana blockchain transaction containing multiple instructions. | Property | Type | Description | | -------------- | ---------------------------------- | ------------------------------------------ | | `instructions` | **[Instruction](#instruction)\[]** | List of instructions to execute atomically | ### Instruction Individual instruction within a Solana transaction. | Property | Type | Description | | ----------- | ---------------------------------- | ------------------------------------------------ | | `accounts` | **[AccountMeta](#accountmeta)\[]** | Accounts involved with their access permissions | | `programId` | `string` | Public key of the Solana program to invoke | | `data` | `string` | Encoded instruction data specific to the program | ### AccountMeta Account metadata specifying permissions for Solana transactions. | Property | Type | Description | | ------------ | --------- | ---------------------------------------------- | | `pubkey` | `string` | Public key of the account | | `isSigner` | `boolean` | Whether this account must sign the transaction | | `isWritable` | `boolean` | Whether this account's data may be modified | ## Token Token information including metadata and chain-specific details. | Property | Type | Description | | ---------- | -------- | ---------------------------------------------- | | `address` | `string` | Contract address of the token | | `symbol` | `string` | Token symbol (e.g., "ETH", "USDC") | | `name` | `string` | Full token name (e.g., "Ethereum", "USD Coin") | | `decimals` | `number` | Number of decimal places for the token | | `chainId` | `number` | Chain ID where this token exists | | `imageUrl` | `string` | URL to the token's logo or icon | ## TokenList Container for a list of tokens on a specific chain. | Property | Type | Description | | -------- | ---------------------- | -------------------------------------- | | `tokens` | **[Token](#token)\[]** | Array of tokens available on the chain | ## Quote Bridge quote containing execution steps and fee information. | Property | Type | Description | | ----------------------- | -------------------------------------- | ----------------------------------------- | | `quoteId` | `string` | Unique identifier for tracking | | `steps` | **[ExecutionStep](#executionstep)\[]** | Transaction steps to execute | | `amountOut` | `bigint` | Expected output amount | | `totalFees` | `bigint` | Total fees in source token | | `provider` | **[QuoteProvider](#quoteprovider)** | Bridge provider | | `estimatedFillTimeSecs` | `number` | Completion time (seconds) | | `deadline` | `Date` | Quote expiration time | | `fees` | `TokenFee[]` | Detailed fee breakdown by token and chain | ## Order A cross-chain bridge order that tracks transaction status and details. | Property | Type | Description | | ---------------------------- | --------------------------------------- | ----------------------------------------------------------- | | `quoteId` | `string` | Unique identifier linking this order to the original quote | | `provider` | **[QuoteProvider](#quoteprovider)** | Provider that processed this order | | `status` | **[OrderStatus](#orderstatus)** | Current status of the cross-chain order | | `sourceTransactionHash` | `string` | Transaction hash on the source chain | | `destinationTransactionHash` | `string` | Transaction hash on the destination chain | | `sourceChain` | **[ChainIdentifier](#chainidentifier)** | Source chain with id and architecture | | `destinationChain` | **[ChainIdentifier](#chainidentifier)** | Destination chain with id and architecture | | `senderAddress` | `string` | Address that initiated the order | | `receiverAddress` | `string` | Address that will receive the tokens | | `amountIn` | `string` | Input amount sent in source token's smallest unit | | `amountOut` | `string` | Output amount received in destination token's smallest unit | | `sourceTokenAddress` | `string` | Contract address of the source token | | `destinationTokenAddress` | `string` | Contract address of the destination token | | `timestamp` | `Date` | Block timestamp of the source transaction | | `lastUpdated` | `Date` | Block timestamp of the last update to the order | | `nextSteps` | **[ExecutionStep](#executionstep)\[]** | Required user actions to complete the order | | `deadline` | `Date \| undefined` | Expiration time when the order becomes eligible for refund | # Enums Enumeration types that define specific sets of values used across the SDK. ## ChainArchitecture Blockchain architecture types supported by the Metalayer SDK. | Architecture | Description | | ------------- | ---------------------------------- | | `UNSPECIFIED` | Unspecified architecture | | `ETHEREUM` | Ethereum and EVM-compatible chains | | `SOLANA` | Solana blockchain | ## QuoteProvider Bridge providers that can process cross-chain transactions. | Provider | Description | | ----------------------- | ---------------------------- | | `UNSPECIFIED` | Unspecified provider | | `NITRO_BRIDGE` | Arbitrum Nitro native bridge | | `BEDROCK_BRIDGE` | OP Stack native bridge | | `ZKSYNC_BRIDGE` | zkSync native bridge | | `ACROSS` | Across protocol bridge | | `ECO` | Eco protocol bridge | | `RELAY` | Relay protocol bridge | | `METATOKEN` | MetaToken bridge | | `LAYER_ZERO_OFT` | LayerZero OFT bridge | | `HYPERLANE_WARP_ROUTES` | Hyperlane Warp Routes bridge | ## OrderStatus Order status values indicating the current state of a cross-chain transaction. | Status | Description | | ------------------- | ----------------------------------------------------------- | | `PENDING` | Order is in progress, waiting for completion | | `WAITING_TO_PROVE` | Withdrawal is waiting for proof submission (native bridges) | | `WITHDRAWAL_PROVEN` | Withdrawal proof has been submitted | | `FULFILLED` | Order completed successfully | | `REFUNDED` | Order was refunded to the source address | | `FAILED` | Order failed and cannot be completed | | `READY_TO_REFUND` | Order deadline passed, eligible for refund | ```typescript theme={null} import { OrderStatus } from '@metalayer/sdk'; const { order } = await client.getOrder({ sourceTransactionHash: '0xTxHash', sourceChainId: 1, }); // Check specific status if (order.status === OrderStatus.FULFILLED) { console.log('Bridge transaction completed!'); } ``` # Client Methods Source: https://docs.caldera.xyz/metalayer/sdk/client-methods Metalayer SDK client methods for cross-chain operations # `MetalayerClient.init(config)` Create an instance of the Metalayer SDK client with your configuration. ### MetalayerConfig | Property | Type | Description | Default | Required | | ---------------- | ----------------------------------------- | ------------------------------------------------ | ----------------------------------- | -------- | | `apiKey` | `string` | Your application's API key for the Metalayer API | - | ✅ | | `environment` | `'mainnet' \| 'testnet'` | The environment to use. | `'mainnet'` | ✅ | | `defaultOptions` | **[MetalayerOptions](#metalayeroptions)** | Default options for the Metalayer client | `{ quotePreference: 'bestReturn' }` | ❌ | | `customApiUrl` | `string` | Override the default API URL for the environment | `undefined` | ❌ | ```typescript theme={null} const client = MetalayerClient.init({ apiKey: 'your-api-key', environment: 'mainnet', defaultOptions: { quotePreference: 'fastest', chainIds: [1, 33139, 42161], // Filter for Ethereum Mainnet, ApeChain, Arbitrum One }, }); ``` ### MetalayerOptions | Property | Type | Description | Default | Required | | ----------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------- | | `quotePreference` | `'bestReturn' \| 'fastest'` | Quote optimization preference for routing | `'bestReturn'` | ❌ | | `chainIds` | `number[]` | Default chain IDs for internal filtering in `getSupportedChains()`, `getTokens()`, and `getOrders()` methods. Can be overridden by method parameters | `undefined` | ❌ | # `client.getSupportedChains(params?)` Get supported blockchain networks. ### Parameters | Property | Type | Description | Default | Required | | ---------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- | | `chainIds` | `number[]` | List of chain IDs to filter. Defaults to all chains or SDK config `chainIds` if not provided. The response will return chain metadata for all chains in this list | SDK config `chainIds` or all chains | ❌ | ```typescript theme={null} // Get all supported chains const { chains } = await client.getSupportedChains(); // Get specific chains only const { chains } = await client.getSupportedChains({ chainIds: [1, 33139, 42161] // Ethereum Mainnet, ApeChain, Arbitrum One }); ``` ### Response | Property | Type | Description | | -------- | -------------------------------------------------- | ------------------------------------------------------------- | | `chains` | **[Chain](/metalayer/sdk/api-reference#chain)\[]** | List of blockchain networks supported for cross-chain routing | # `client.getTokens(params?)` Get token information by chain. ### Parameters | Property | Type | Description | Default | Required | | ---------- | ---------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- | | `chainIds` | `number[]` | Filters tokens by chain ID presence in this list. Defaults to all chains or SDK config `chainIds` if not provided | SDK config `chainIds` or all chains | ❌ | ```typescript theme={null} // Get tokens for all supported chains const { tokensByChain } = await client.getTokens(); // Get tokens for specific chains const { tokensByChain } = await client.getTokens({ chainIds: [1, 33139, 42161] // Ethereum Mainnet, ApeChain, Arbitrum One }); ``` ### Response | Property | Type | Description | | --------------- | --------------------------------------------------------------------------- | ------------------------------------------------------ | | `tokensByChain` | `Record` | Mapping of chain ID to available tokens for that chain | # `client.quote(params)` Get quotes for cross-chain bridging. ### Parameters | Property | Type | Description | Default | Required | | ------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------- | --------------- | --------------------------- | | `sourceChainId` | `number` | Source chain ID | - | ✅ | | `sourceTokenAddress` | `string` | Source token address | - | ✅ | | `destinationChainId` | `number` | Destination chain ID | - | ✅ | | `destinationTokenAddress` | `string` | Destination token address | - | ✅ | | `amount` | `BigInt` | Amount to swap | - | ✅ | | `senderAddress` | `string` | Sender wallet address | - | ✅ | | `receiverAddress` | `string` | Receiver wallet address. Required when bridging between different architectures (e.g., Ethereum → Solana) | `senderAddress` | ❌ (✅ if cross-architecture) | | `quotePreference` | `'bestReturn' \| 'fastest'` | Quote optimization preference | `'bestReturn'` | ❌ | ```typescript theme={null} const response = await client.quote({ sourceChainId: 1, sourceTokenAddress: '0x0000000000000000000000000000000000000000', destinationChainId: 33139, destinationTokenAddress: '0x0000000000000000000000000000000000000000', amount: BigInt('1000000000000000000'), senderAddress: '0xYourAddress', }); ``` ### Response | Property | Type | Description | | ------------------ | ------------------------------------------------------------------- | ------------------------------------------- | | `sourceChain` | **[ChainIdentifier](/metalayer/sdk/api-reference#chainidentifier)** | Source chain information | | `destinationChain` | **[ChainIdentifier](/metalayer/sdk/api-reference#chainidentifier)** | Destination chain information | | `sourceToken` | **[Token](/metalayer/sdk/api-reference#token)** | Source token information | | `destinationToken` | **[Token](/metalayer/sdk/api-reference#token)** | Destination token information | | `quotes` | **[Quote](/metalayer/sdk/api-reference#quote)\[]** | Array of quotes sorted by `quotePreference` | # `client.getOrder(params)` Get order details for a specific transaction. ### Parameters | Property | Type | Description | Default | Required | | ----------------------- | -------- | ---------------- | ------- | -------- | | `sourceTransactionHash` | `string` | Transaction hash | - | ✅ | | `sourceChainId` | `number` | Source chain ID | - | ✅ | ```typescript theme={null} const response = await client.getOrder({ sourceTransactionHash: '0xTxHash', sourceChainId: 1, }); ``` ### Response | Property | Type | Description | | -------- | ----------------------------------------------- | ----------------------------------------- | | `order` | **[Order](/metalayer/sdk/api-reference#order)** | The order matching the request identifier | ```typescript theme={null} import { OrderStatus } from '@metalayer/sdk'; const { order } = await client.getOrder({ sourceTransactionHash: '0xTxHash', sourceChainId: 1, }); // Check specific status if (order.status === OrderStatus.FULFILLED) { console.log('Bridge transaction completed!'); } ``` # `client.getOrders(params)` Returns a list of orders for a wallet address. ### Parameters | Property | Type | Description | Default | Required | | ---------- | ---------- | ------------------------------------------------------------------------------------------------------------ | ----------------------------------- | -------- | | `address` | `string` | Wallet address to get orders for | - | ✅ | | `chainIds` | `number[]` | List of chain IDs to filter the orders from. Defaults to all chains or SDK config `chainIds` if not provided | SDK config `chainIds` or all chains | ❌ | ```typescript theme={null} // Get all orders for a wallet const response = await client.getOrders({ address: '0xWalletAddress', }); // Get orders filtered by specific chains const response = await client.getOrders({ address: '0xWalletAddress', chainIds: [1, 33139, 42161], // Ethereum Mainnet, Ape Chain, Arbitrum One }); ``` ### Response | Property | Type | Description | | -------- | ------------------------------------------------------------------- | ------------------------------------------------------ | | `orders` | **[Order](/metalayer/sdk/api-reference#order)\[]** | List of orders for the requested address | | `tokens` | `Record` | Token metadata indexed by "chainId\_tokenAddress" keys | # Examples Source: https://docs.caldera.xyz/metalayer/sdk/examples Step-by-step examples of using the Metalayer SDK ## Client Example Basic implementation steps for building a cross-chain bridge using the Metalayer client directly. ### 1. Initialize Client Set up the Metalayer client with your API key to access bridge functionality. ```typescript theme={null} import { MetalayerClient, OrderStatus } from '@metalayer/sdk'; const client = MetalayerClient.init({ apiKey: process.env.METALAYER_API_KEY!, environment: 'mainnet', }); ``` ### 2. Get Supported Chains Fetch available chains to determine valid bridge routes for your application. ```typescript theme={null} const { chains } = await client.getSupportedChains(); console.log('Available chains:', chains); ``` ### 3. Get Tokens Retrieve token information for the chains you want to support in your bridge interface. ```typescript theme={null} const { tokensByChain } = await client.getTokens(); const ethereumTokens = tokensByChain[1] || []; ``` ### 4. Request Quote Get bridge quotes based on user selections to show routing options and fees. ```typescript theme={null} const quoteResponse = await client.quote({ sourceChainId: 1, // Ethereum Mainnet sourceTokenAddress: '0x0000000000000000000000000000000000000000', // ETH destinationChainId: 33139, // ApeChain destinationTokenAddress: '0x0000000000000000000000000000000000000000', // ETH amount: BigInt('1000000000000000000'), // 1 ETH senderAddress: '0xYourWalletAddress', }); const bestQuote = quoteResponse.quotes[0]; ``` ### 5. Execute Transaction Execute the bridge transaction by processing each step in the quote with your wallet client. ```typescript theme={null} for (const step of bestQuote.steps) { switch (step.action.case) { case 'transactionRequest': const hash = await walletClient.sendTransaction({ to: step.action.value.to, data: step.action.value.data, value: step.action.value.value, }); break; case 'eip712Data': await walletClient.signTypedData(step.action.value); break; } } ``` ### 6. Monitor Status Track the bridge transaction progress to provide status updates to users. ```typescript theme={null} const order = await client.getOrder({ sourceTransactionHash: '0xTxHash', sourceChainId: 1, }); if (order.status === OrderStatus.FULFILLED) { console.log('Bridge completed successfully!'); } else if (order.status === OrderStatus.FAILED) { console.log('Bridge failed'); } else if (order.status === OrderStatus.PENDING) { console.log('Bridge in progress...'); } ``` ## React Hook Example Basic implementation steps for building a cross-chain bridge using Metalayer SDK hooks. For detailed hook configuration and provider setup, see [Hooks](/metalayer/sdk/hooks). ### 1. Get Supported Chains Fetch the list of supported chains to populate source and destination chain selectors in your UI. This data enables users to choose which networks they want to bridge between. ```tsx theme={null} import { useSupportedChains } from '@metalayer/sdk'; const { data: chainsData } = useSupportedChains(); const chains = chainsData?.chains || []; ``` ### 2. Get Tokens Retrieve available tokens organized by chain to build token selection lists. Use this data to create filtered token dropdowns that update based on the user's selected source and destination chains. ```tsx theme={null} import { useTokens } from '@metalayer/sdk'; const { data: tokensData } = useTokens(); const tokens = tokensData?.tokensByChain || {}; ``` ### 3. Get Quote Request bridge quotes based on user selections from your UI. This provides routing options, fees, and estimated completion times for the bridge transaction. ```tsx theme={null} import { useQuote } from '@metalayer/sdk'; const { data: quoteData, isLoading } = useQuote({ sourceChainId: 1, // Ethereum Mainnet sourceTokenAddress: '0x0000000000000000000000000000000000000000', // ETH destinationChainId: 33139, // ApeChain destinationTokenAddress: '0x0000000000000000000000000000000000000000', // ETH amount: BigInt('1000000000000000000'), // 1 ETH senderAddress: '0xYourWalletAddress', }); const bestQuote = quoteData?.quotes[0]; ``` ### 4. Execute Transaction Execute the bridge transaction using the selected quote. This typically involves multiple steps like token approvals followed by the actual bridge transaction, with each step requiring user wallet confirmation. ```typescript theme={null} // Execute quote steps for (const step of bestQuote.steps) { switch (step.action.case) { case 'transactionRequest': await walletClient.sendTransaction({ to: step.action.value.to, data: step.action.value.data, value: step.action.value.value, }); break; case 'eip712Data': await walletClient.signTypedData(step.action.value); break; } } ``` ### 5. Monitor Status Track the bridge transaction progress to provide real-time status updates to users. Use this to display progress indicators, completion confirmations, or error states in your UI. ```tsx theme={null} import { useOrderPolling, OrderStatus } from '@metalayer/sdk'; const { data: order } = useOrderPolling({ sourceTransactionHash: '0xTxHash', sourceChainId: 1, }); // Check order status - see OrderStatus Values section for all possible values if (order?.status === OrderStatus.FULFILLED) { console.log('Bridge completed successfully!'); } else if (order?.status === OrderStatus.FAILED) { console.log('Bridge failed'); } else if (order?.status === OrderStatus.PENDING) { console.log('Bridge in progress...'); } ``` # Getting Started Source: https://docs.caldera.xyz/metalayer/sdk/getting-started Get started with the Metalayer SDK for cross-chain interoperability ## Features * Cross-chain quote aggregation * Full TypeScript support * React hooks integration * Viem compatibility **Looking for a pre-built UI?** If you want to execute bridge transactions with a ready-made interface, consider using the [Metalayer Widget](/metalayer/widget/getting-started) instead. The Widget uses this SDK under the hood and provides a production-ready UI with built-in theming, wallet integration, and automatic transaction handling. ## Installation ```bash pnpm theme={null} pnpm add viem @metalayer/sdk ``` ```bash npm theme={null} npm install viem @metalayer/sdk ``` ```bash yarn theme={null} yarn add viem @metalayer/sdk ``` If you plan to use the SDK's React hooks, you'll need to install React Query as a peer dependency. ### Installing React Query ```bash pnpm theme={null} pnpm add @tanstack/react-query ``` ```bash npm theme={null} npm install @tanstack/react-query ``` ```bash yarn theme={null} yarn add @tanstack/react-query ``` ## API Key Setup Contact our team to get your API key. ## Requirements * Node.js 20+ * TypeScript 5.0+ (recommended) * React 16+ (for hooks) * Viem 2.0+ (peer dependency) ## Next Steps For complete implementation examples and detailed bridge flows, see [Examples](/metalayer/sdk/examples). # React Hooks Source: https://docs.caldera.xyz/metalayer/sdk/hooks React hooks for the Metalayer SDK ## Setup ```tsx theme={null} import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { MetalayerProvider, type MetalayerConfig } from '@metalayer/sdk'; const queryClient = new QueryClient(); const config: MetalayerConfig = { apiKey: 'your-api-key', environment: 'mainnet', }; function App() { return ( ); } ``` ## Available Hooks ### `useSupportedChains()` Get supported blockchain networks. ```tsx theme={null} import { useSupportedChains } from '@metalayer/sdk'; const { data, isLoading, error } = useSupportedChains(); const chains = data?.chains; ``` ### `useTokens(params?)` Get token information by chain. ```tsx theme={null} import { useTokens } from '@metalayer/sdk'; const { data, isLoading } = useTokens({ chainId: 1 // Optional: filter by chain }); const tokensByChain = data?.tokensByChain; ``` ### `useQuote(params, interval?)` Get quotes for cross-chain bridging with real-time updates. ```tsx theme={null} import { useQuote } from '@metalayer/sdk'; const { quote, // Best quote based on preferences (default: 'bestReturn') quotes, // Full list of quotes isLoading, error, refetch } = useQuote({ sourceChainId: 1, sourceTokenAddress: '0x...', destinationChainId: 33139, destinationTokenAddress: '0x...', amount: BigInt('1000000000000000000'), senderAddress: '0x...', }); ``` ### `useOrderPolling(params, interval?)` Poll order status with automatic updates. ```tsx theme={null} import { useOrderPolling } from '@metalayer/sdk'; const { data: order, isLoading, error } = useOrderPolling({ sourceTransactionHash: '0xTxHash', sourceChainId: 1, }, 15000); // Poll every 15 seconds ``` ### `useWalletOrders(address)` Get all orders for a specific wallet address. ```tsx theme={null} import { useWalletOrders } from '@metalayer/sdk'; const { data: orders, isLoading, error } = useWalletOrders('0xWalletAddress'); ``` ### `useMetalayer()` Access the Metalayer client instance for direct API calls. ```tsx theme={null} import { useMetalayer } from '@metalayer/sdk'; function Component() { const { router } = useMetalayer(); // Use router directly for client method calls const handleQuote = async () => { const quote = await router.quote({ sourceChainId: 1, destinationChainId: 33139, // ... other params }); }; return
Use router for direct API calls
; } ``` # Utilities Source: https://docs.caldera.xyz/metalayer/sdk/utilities SDK utility functions for common operations ## Utility Functions The SDK provides utility functions for common operations: ### `chainToViemChain(chain)` Convert a Metalayer [Chain](/metalayer/sdk/api-reference#chain) object to Viem chain format. Use the result as your **wagmi `chains`** list and pass the same viem `Chain` values into **`@metalayer/widget`** helpers such as [`createWidgetTransport`](/metalayer/widget/components#createwidgettransport-chain), [`createWidgetClient`](/metalayer/widget/components#createwidgetclient-chain), and [`createWidgetTransportsRecord`](/metalayer/widget/components#createwidgettransportsrecord-chains) (see [Widget Components](/metalayer/widget/components#rpc-transport-helpers)). ```typescript theme={null} import { chainToViemChain } from '@metalayer/sdk'; const viemChain = chainToViemChain(chain); ``` ### `chainsToViemChains(chains)` Convert an array of Metalayer [Chain](/metalayer/sdk/api-reference#chain) objects to an array of Viem chains. Invalid or non-EVM chains are filtered out. The returned array is suitable for wagmi and for the widget transport helpers linked above. ```typescript theme={null} import { chainsToViemChains } from '@metalayer/sdk'; const viemChains = chainsToViemChains(chains); ``` ### `collectChainHttpRpcUrls(chain)` Collects unique **HTTP** RPC URLs from a viem `Chain` produced by **`chainToViemChain`**, in Metalayer order: URLs under **`rpcUrls.default`**, then alternate slots **`rpc-0`**, **`rpc-1`**, … (sorted by index), which map to **`alternativeRpcs`** from the Metalayer chain. Used internally by **`createWidgetTransport`** in `@metalayer/widget`; you can use it directly when building custom viem **`fallback()`** stacks or other transports. ```typescript theme={null} import { collectChainHttpRpcUrls } from '@metalayer/sdk'; const urls = collectChainHttpRpcUrls(viemChain); ``` ### `formatQuoteProvider(provider)` Format a [QuoteProvider](/metalayer/sdk/api-reference#quoteprovider) enum value to a readable string. ```typescript theme={null} import { formatQuoteProvider, QuoteProvider } from '@metalayer/sdk'; const name = formatQuoteProvider(QuoteProvider.ACROSS); // "Across" ``` # Bridge Aggregator Source: https://docs.caldera.xyz/metalayer/solutions/bridge-aggregation Unified cross-chain transfers with optimal routing across 50+ networks Caldera's bridge aggregator provides a single interface for cross-chain transfers while intelligently routing through the best available bridge provider for each transaction. Instead of users navigating multiple bridge UIs with different security models and wait times, the bridge aggregator aggregates quotes and presents the optimal route. ## The Problem Traditional cross-chain transfers require users to: * **Choose between multiple bridges** with different trade-offs * **Navigate separate interfaces** for each bridge provider * **Understand complex security models** and settlement times * **Manage wrapped tokens** and liquidity requirements ## Single Interface, Multiple Providers Metalayer provides unified access to cross-chain transfers through: * **[SDK](/metalayer/sdk/getting-started)**: Complete developer toolkit for custom applications * **[Widget](/metalayer/widget/getting-started)**: Embeddable UI component for instant deployment Behind this single interface, Metalayer aggregates quotes from [multiple bridge providers](/metalayer/resources/aggregated-bridges) across [50+ supported networks](/metalayer/resources/widget-supported-chains), selecting the optimal route for each transfer. ## Next Steps Complete integration guide Embed ready-made UI # MetaToken: Omnichain Tokens Source: https://docs.caldera.xyz/metalayer/solutions/omnichain-tokens Universal token portability with the same address on every chain Metatoken establishes a new standard for multichain tokens, allowing any asset to be universally portable across multiple chains with the same contract address on every network. Unlike traditional wrapped tokens that fragment liquidity, Metatoken maintains unified supply while enabling seamless cross-chain transfers. ## The Problem Traditional tokens face critical limitations in a multichain world: * **Asset Isolation**: Tokens trapped on their origin chains * **Fragmented Liquidity**: Multiple wrapped versions across different networks * **Complex Deployments**: Expensive and time-consuming multi-chain launches * **Poor UX**: Users confused by different token addresses on each chain * **Security Risks**: Third-party bridges controlling token movement ## How It Works ### Hub-Spoke Architecture Metatoken uses a Hub-Spoke model with specialized contracts: * **MetaERC20Hub**: Deployed on the token's home chain, locks/unlocks canonical tokens * **MetaERC20Spoke**: Deployed on remote chains, mints/burns synthetic tokens * **Security Threshold Routing**: High-value spoke-to-spoke transfers routed through hub for validation ### Transfer Flows 1. **Hub → Spoke**: Lock canonical tokens on hub, mint synthetic tokens on spoke 2. **Spoke → Hub**: Burn synthetic tokens on spoke, unlock canonical tokens on hub 3. **Spoke → Spoke (Low Value)**: Direct burn and mint between spokes 4. **Spoke → Spoke (High Value)**: Routed through hub with validator approval for security This maintains unified supply across all networks with the same contract address everywhere. ## Key Benefits * **Unified Supply**: Single global token supply, no wrapped token confusion * **Capital Efficient**: No liquidity pools or slippage, always 1:1 exchange * **Deterministic Addresses**: Same contract address on every chain * **Security Controls**: Configurable thresholds and validator approval for high-value transfers * **Emergency Recovery**: Admin functions for handling stuck transfers while maintaining conservation of funds * **Cost-Effective**: Included with Caldera rollup deployments ## Deployment MetaTokens are currently deployed and managed by Caldera. This ensures proper security configuration, validator setup, and integration with the Metalayer infrastructure. Projects interested in deploying their token as a MetaToken should contact our team to discuss requirements, timeline, and integration process. ## Next Steps Discuss omnichain token deployment Review contract architecture # Components & API Source: https://docs.caldera.xyz/metalayer/widget/components Complete API reference for the Metalayer Bridge Widget components ## WidgetProvider The provider component that sets up the widget context and configuration. ### Props | Prop | Type | Description | Default | Required | | ----------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------- | ----------- | -------- | | `sdkConfig` | **[MetalayerConfig](/metalayer/sdk/client-methods#metalayerconfig)** | SDK configuration | - | ✅ | | `theme` | **[WidgetTheme](/metalayer/widget/theming#widgettheme)** | Theme configuration for customizing colors, corners, shadows, and more | `undefined` | ❌ | | `defaultSource` | **[DefaultChainToken](#defaultchaintoken)** | Default source chain and token | `undefined` | ❌ | | `defaultDestination` | **[DefaultChainToken](#defaultchaintoken)** | Default destination chain and token | `undefined` | ❌ | | `enabledChains` | **[Chain](/metalayer/sdk/api-reference#chain)\[]** | Pre-loaded chains (bypasses fetching) | `undefined` | ❌ | | `onSupportedChainsLoad` | `(chains: Chain[]) => void` | Callback when chains are loaded | `undefined` | ❌ | | `onError` | `(error: Error) => void` | Error handling callback | `undefined` | ❌ | | `debugEnabled` | `boolean` | Enable debug logging | `false` | ❌ | ### SDK Configuration ```tsx Basic Configuration theme={null} ``` ```tsx With Custom Options theme={null} ``` The `defaultOptions` configuration is optional. When not specified, the widget will display all supported chains and use default quote preference. ### Default Source and Destination ```tsx theme={null} ``` ### Chain Loading Callback `onSupportedChainsLoad` receives Metalayer [Chain](/metalayer/sdk/api-reference#chain) values from the SDK. Convert them with **[chainsToViemChains](/metalayer/sdk/utilities#chainstoviem)** or **[chainToViemChain](/metalayer/sdk/utilities#chaintoviem)** before passing them to wagmi, viem, or the [RPC transport helpers](#rpc-transport-helpers) below. ```tsx theme={null} import { chainsToViemChains } from '@metalayer/sdk'; import { WidgetProvider } from '@metalayer/widget'; { const viemChains = chainsToViemChains(chains); updateWalletConfig(viemChains); }} > ``` #### Wagmi client callback (recommended) Use **[createWidgetClient](#createwidgetclient-chain)** so each chain’s public client uses Metalayer’s RPC ordering and fallbacks. Build a non-empty viem chain tuple from `chainsToViemChains(metalayerChains)` (or a filtered list). Below, `ViemChain` is viem’s `Chain` type under an alias so it is not confused with the Metalayer `Chain` from the SDK. ```tsx theme={null} import { chainsToViemChains } from '@metalayer/sdk'; import { createWidgetClient } from '@metalayer/widget'; import type { Chain as ViemChain } from 'viem'; import { createConfig } from 'wagmi'; function createWagmiConfig(chains: [ViemChain, ...ViemChain[]]) { return createConfig({ chains, multiInjectedProviderDiscovery: false, client({ chain }) { return createWidgetClient(chain); }, }); } ``` > **📋 Note**: The widget requires an external `WagmiProvider` — it does not create its own. Use `onSupportedChainsLoad` to update your wagmi config with the widget's supported chains. ### RPC transport helpers These helpers take **viem [`Chain`](https://viem.sh/docs/glossary/types#chain)** objects—the same shape returned by **`chainToViemChain`** / **`chainsToViemChains`** in `@metalayer/sdk`. Internally, **`createWidgetTransport`** calls **`collectChainHttpRpcUrls`** (see [SDK utilities](/metalayer/sdk/utilities#collectchainhttprpcurls-chain)) and builds a viem **`fallback`** transport over those HTTP URLs: Metalayer **default RPC** first, then **`rpc-0`**, **`rpc-1`**, … slots that **`chainToViemChain`** fills from **`alternativeRpcs`**. If no URLs are present, it falls back to viem’s default **`http()`** behavior. #### `createWidgetTransport(chain)` Returns a viem **`Transport`** for a single chain. It reads every HTTP RPC URL from the chain via **[`collectChainHttpRpcUrls`](/metalayer/sdk/utilities#collectchainhttprpcurls-chain)** and wraps them in a viem **`fallback()`** transport, so requests automatically retry on the next endpoint when one is rate-limited or unavailable. If no URLs are present it returns a plain `http()` transport. Most integrations should use **[`createWidgetClient`](#createwidgetclient-chain)** (wagmi `client` callback) or **[`createWidgetTransportsRecord`](#createwidgettransportsrecord-chains)** (wagmi `transports` map) instead of calling this directly. Use `createWidgetTransport` when you need the raw transport for a custom viem client or want to compose it with other transports: ```typescript theme={null} import { createWidgetTransport } from '@metalayer/widget'; import { createClient } from 'viem'; const client = createClient({ chain: viemChain, transport: createWidgetTransport(viemChain), }); ``` #### `createWidgetClient(chain)` Convenience wrapper: creates a viem **`Client`** with `createWidgetTransport` already wired in. This is the recommended way to configure wagmi via the **`client`** callback (see [Wagmi client callback](#wagmi-client-callback-recommended) above). ```typescript theme={null} import { createWidgetClient } from '@metalayer/widget'; const client = createWidgetClient(viemChain); ``` #### `createWidgetTransportsRecord(chains)` Builds **`Record`** keyed by chain id. Useful with RainbowKit’s `getDefaultConfig` or any wagmi setup that takes a `transports` map instead of a `client` callback: ```typescript theme={null} import { createWidgetTransportsRecord } from '@metalayer/widget'; import { getDefaultConfig } from '@rainbow-me/rainbowkit'; const config = getDefaultConfig({ appName: 'My App', projectId: 'your-walletconnect-project-id', chains: supportedChains as unknown as readonly [Chain, ...Chain[]], transports: createWidgetTransportsRecord(supportedChains), }); ``` For custom transport stacks (for example viem **`fallback()`**), you can read ordered HTTP URLs from a viem chain with **[collectChainHttpRpcUrls](/metalayer/sdk/utilities#collectchainhttprpcurls-chain)** in `@metalayer/sdk`. ### Theme Configuration The widget supports extensive theming options including predefined themes, custom colors, fonts, and advanced overrides. See the **[Theming](/metalayer/widget/theming)** page for complete customization options and visual examples. ## Widget The main UI component that renders the bridge interface. ### Props See **[WidgetProps](#widgetprops)** for the complete props reference. ```tsx theme={null} openWalletModal()} onDisconnectClick={() => disconnect()} solanaSigner={solanaSigner} /> ``` ## Type Definitions ### MetalayerConfig SDK configuration object. See **[MetalayerConfig](/metalayer/sdk/client-methods#metalayerconfig)** in the SDK documentation for full details. ### WidgetProps | Property | Type | Description | Default | Required | | ------------------------ | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ----------- | -------- | | `onConnectClick` | `() => void` | Callback when user clicks connect | - | ✅ | | `onDisconnectClick` | `() => void` | Callback when user clicks disconnect. When provided, widget manages wallet connection internally | `undefined` | ❌ | | `onTransactionSubmitted` | `(sourceChainId?: number, destChainId?: number, amount?: string) => void` | Callback when user submits a transaction | `undefined` | ❌ | | `onTokenSelected` | `(direction: 'source' \| 'destination', chainId: number, tokenAddress: string) => void` | Callback when user selects a token | `undefined` | ❌ | | `source` | `{ chainId: number; tokenAddress?: string }` | Controlled source chain and token | `undefined` | ❌ | | `destination` | `{ chainId: number; tokenAddress?: string }` | Controlled destination chain and token | `undefined` | ❌ | | `isConnecting` | `boolean` | Whether a wallet is connecting | `false` | ❌ | | `solanaSigner` | **[WidgetSolanaSigner](#widgetsolanasigner)** | Solana wallet signer for Solana transactions | `undefined` | ❌ | | `className` | `string` | CSS class name for custom styling | `undefined` | ❌ | When `onDisconnectClick` is provided, the widget manages wallet connection state internally and displays wallet info in the settings tab. If your page already handles wallet connect/disconnect logic, you don't need to set this prop; the widget will work with your existing wallet connection management. ```tsx theme={null} import type { WidgetProps } from '@metalayer/widget'; ``` ### WidgetSolanaSigner Solana support is currently in beta and requires additional dependencies. See the [EVM + Solana installation](/metalayer/widget/getting-started#evm--solana-beta) for setup instructions. | Property | Type | Description | Default | Required | | ----------------- | ---------------------------------------------------- | ----------------------------------------------------- | ------- | -------- | | `address` | `string` | Solana wallet address | - | ✅ | | `isConnected` | `() => boolean` | Function that returns whether the wallet is connected | - | ✅ | | `signTransaction` | `(transaction: Transaction) => Promise` | Function to sign a Solana transaction | - | ✅ | ```tsx theme={null} const solanaSigner = { address: wallet.publicKey.toString(), isConnected: () => wallet.connected, signTransaction: async (transaction) => await wallet.signTransaction(transaction), }; ``` ### DefaultChainToken ```tsx theme={null} interface DefaultChainToken { chainId: number; tokenAddress: string; } ``` | Property | Type | Description | Default | Required | | -------------- | -------- | ------------------------------- | ------- | -------- | | `chainId` | `number` | Chain ID of the default network | - | ✅ | | `tokenAddress` | `string` | Token contract address | - | ✅ | ## Utility Functions * **RPC transport helpers** — [`createWidgetTransport`](#createwidgettransport-chain), [`createWidgetClient`](#createwidgetclient-chain), and [`createWidgetTransportsRecord`](#createwidgettransportsrecord-chains) (see [above](#rpc-transport-helpers)). * **Chain conversion** (from `@metalayer/sdk`) feeds those helpers; see [SDK Utilities](/metalayer/sdk/utilities): * **[chainsToViemChains](/metalayer/sdk/utilities#chainstoviem)** — batch convert; skips invalid / non-EVM chains * **[chainToViemChain](/metalayer/sdk/utilities#chaintoviem)** — single Metalayer chain → viem `Chain` * **[collectChainHttpRpcUrls](/metalayer/sdk/utilities#collectchainhttprpcurls-chain)** — ordered HTTP RPC URLs on a viem `Chain` (for custom transports) ## CSS Styling The widget requires a CSS import for proper styling: ```tsx theme={null} import '@metalayer/widget/styles.css'; ``` ## Error Handling ### Error Callback Handle errors in the widget through the `onError` callback: ```tsx theme={null} { console.error('Widget error:', error); // Handle error (show toast, log to service, etc.) }} > ``` # Examples Source: https://docs.caldera.xyz/metalayer/widget/examples Step-by-step examples of integrating the Metalayer Bridge Widget ## Dynamic.xyz Integration Complete integration with Dynamic.xyz for multi-chain wallet support. This example includes Solana wallet support, which is currently in beta and requires additional dependencies. See the [EVM + Solana installation](/metalayer/widget/getting-started#evm--solana-beta) for setup instructions. ```tsx theme={null} import { EthereumWalletConnectors } from '@dynamic-labs/ethereum'; import { DynamicContextProvider, mergeNetworks, useDynamicContext } from '@dynamic-labs/sdk-react-core'; import { SolanaWalletConnectors, isSolanaWallet } from '@dynamic-labs/solana'; import { DynamicWagmiConnector } from '@dynamic-labs/wagmi-connector'; import { chainToViemChain, ChainArchitecture } from '@metalayer/sdk'; import { createWidgetClient, WidgetProvider, Widget } from '@metalayer/widget'; import { useState, useMemo } from 'react'; import type { Chain as ViemChain } from 'viem/chains'; import { mainnet } from 'viem/chains'; import { createConfig, WagmiProvider } from 'wagmi'; function createWagmiConfig(chains: [ViemChain, ...ViemChain[]]) { return createConfig({ chains, multiInjectedProviderDiscovery: false, client({ chain }) { return createWidgetClient(chain); }, }); } function App() { const [evmNetworks, setEvmNetworks] = useState([]); const [viemChains, setViemChains] = useState([mainnet]); const wagmiConfig = useMemo( () => createWagmiConfig(viemChains as [ViemChain, ...ViemChain[]]), [viemChains], ); return ( mergeNetworks(evmNetworks, networks), }, }} > { const ethereumChains = chains.filter( (chain) => chain.identifier?.architecture === ChainArchitecture.ETHEREUM, ); const nextViem = ethereumChains.map((chain) => chainToViemChain(chain)); setViemChains(nextViem.length ? nextViem : [mainnet]); setEvmNetworks( ethereumChains.map((chain) => viemChainToEvmNetwork(chainToViemChain(chain), chain.imageUrl), ), ); }} onError={(error) => console.error('Widget error:', error)} > ); } function WidgetWrapper() { const { setShowAuthFlow, primaryWallet } = useDynamicContext(); const solanaSigner = useMemo(() => { if (!primaryWallet || !isSolanaWallet(primaryWallet)) return undefined; return { address: primaryWallet.address, isConnected: () => !!primaryWallet.address, signTransaction: async (transaction) => { const signer = await primaryWallet.getSigner(); return await signer.signTransaction(transaction); }, }; }, [primaryWallet]); return ( setShowAuthFlow(true)} /> ); } // `ViemChain` is viem's Chain (imported above as `Chain as ViemChain`). // Helper function to convert Viem chain to EVM network function viemChainToEvmNetwork(viemChain, iconUrl) { return { chainId: viemChain.id, name: viemChain.name, networkId: viemChain.id, nativeCurrency: viemChain.nativeCurrency, rpcUrls: Object.values(viemChain.rpcUrls.default).flat(), blockExplorerUrls: viemChain.blockExplorers?.default?.url ? [viemChain.blockExplorers.default.url] : [], isTestnet: viemChain.testnet, iconUrls: iconUrl ? [iconUrl] : [], }; } ``` ## RainbowKit Integration ```tsx theme={null} import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { RainbowKitProvider, getDefaultConfig, useConnectModal } from '@rainbow-me/rainbowkit'; import { chainsToViemChains } from '@metalayer/sdk'; import { createWidgetTransportsRecord, WidgetProvider, Widget } from '@metalayer/widget'; import { useMemo, useState } from 'react'; import type { Chain as ViemChain } from 'viem/chains'; import { mainnet } from 'wagmi/chains'; import { WagmiProvider } from 'wagmi'; const queryClient = new QueryClient(); function App() { const [viemChains, setViemChains] = useState([mainnet]); const wagmiConfig = useMemo( () => getDefaultConfig({ appName: 'My App', projectId: 'your-walletconnect-project-id', chains: viemChains as [ViemChain, ...ViemChain[]], transports: createWidgetTransportsRecord(viemChains), }), [viemChains], ); return ( { const next = chainsToViemChains(chains); if (next.length) setViemChains(next); }} > ); } function BridgePage() { const { openConnectModal } = useConnectModal(); return ( ); } ``` ## Privy Integration Complete integration with Privy for multi-chain wallet support with external wagmi configuration. ```tsx theme={null} import { type Chain, ChainArchitecture, chainToViemChain } from '@metalayer/sdk'; import { createWidgetTransportsRecord, WidgetProvider } from '@metalayer/widget'; import { PrivyProvider } from '@privy-io/react-auth'; import { createConfig, WagmiProvider } from '@privy-io/wagmi'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import type { Chain as ViemChain } from 'viem/chains'; import { mainnet } from 'viem/chains'; const queryClient = new QueryClient(); function Providers({ children }: { children: React.ReactNode }) { const [supportedChains, setSupportedChains] = useState([mainnet]); const wagmiConfig = useMemo( () => createConfig({ chains: supportedChains as [ViemChain, ...ViemChain[]], transports: createWidgetTransportsRecord(supportedChains), }), [supportedChains], ); return ( { // Filter for EVM chains and convert to viem chains const evmChains = chains .filter(chain => chain.identifier?.architecture === ChainArchitecture.ETHEREUM) .map(chain => chainToViemChain(chain)); setSupportedChains(evmChains); }} > {children} ); } ``` ```tsx theme={null} import { Widget } from '@metalayer/widget'; import { usePrivy } from '@privy-io/react-auth'; function BridgePage() { const { login, authenticated } = usePrivy(); return ( { if (!authenticated) login(); }} /> ); } ``` ## Next.js Setup ### App Router In your `layout.tsx`: ```tsx theme={null} import '@metalayer/widget/styles.css'; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {children} ); } ``` ### Pages Router In your `_app.tsx`: ```tsx theme={null} import '@metalayer/widget/styles.css'; export default function App({ Component, pageProps }) { return ( ); } ``` ## Vite Setup When using the widget with Vite, you'll need to configure Node.js polyfills: **Install the plugin:** ```bash pnpm theme={null} pnpm add -D vite-plugin-node-polyfills ``` ```bash npm theme={null} npm install --save-dev vite-plugin-node-polyfills ``` ```bash yarn theme={null} yarn add -D vite-plugin-node-polyfills ``` **Update your `vite.config.ts`:** ```tsx theme={null} import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import { nodePolyfills } from 'vite-plugin-node-polyfills'; export default defineConfig({ plugins: [ react(), // Add this plugin to your existing plugins array nodePolyfills({ globals: { Buffer: true, global: true, process: true, }, }), ], // ... your other config options }); ``` If you already have other plugins configured, simply add the `nodePolyfills` plugin to your existing `plugins` array. ## Advanced Configuration Configure the widget with advanced options for production use. ```tsx theme={null} import { chainsToViemChains } from '@metalayer/sdk'; import { WidgetProvider, Widget } from '@metalayer/widget'; function AdvancedBridgeApp() { return ( { const viemChains = chainsToViemChains(chains); if (viemChains.length) { /* Recreate wagmi with viemChains + createWidgetClient or createWidgetTransportsRecord (see Widget Components docs) */ } }} onError={(error) => { // Send to error tracking service console.error('Widget error:', error); // trackError(error); }} debugEnabled={process.env.NODE_ENV === 'development'} > { // Your wallet connection logic openWalletModal(); }} solanaSigner={getSolanaSigner()} // If supporting Solana /> ); } ``` ## Analytics Integration Track widget usage and user interactions: ```tsx theme={null} import { WidgetProvider, Widget } from '@metalayer/widget'; function AnalyticsEnabledWidget() { const trackEvent = (eventName, properties) => { // Your analytics implementation analytics.track(eventName, properties); }; return ( { trackEvent('widget_chains_loaded', { chainCount: chains.length }); }} > { trackEvent('wallet_connect_initiated'); openWalletModal(); }} onTransactionSubmitted={( sourceChainId: number, destChainId?: number, amount?: string ) => { trackEvent('bridge_transaction_submitted', { sourceChainId, destChainId, amount }); }} /> ); } ``` # Getting Started Source: https://docs.caldera.xyz/metalayer/widget/getting-started Get started with the Metalayer Bridge Widget for cross-chain token bridging ## Features * Cross-chain token bridging * Multi-wallet support (Ethereum + Solana) * Responsive design * Framework agnostic * Type-safe with TypeScript ## Installation ### EVM Only ```bash pnpm theme={null} pnpm add viem wagmi @tanstack/react-query @metalayer/sdk @metalayer/widget ``` ```bash npm theme={null} npm install viem wagmi @tanstack/react-query @metalayer/sdk @metalayer/widget ``` ```bash yarn theme={null} yarn add viem wagmi @tanstack/react-query @metalayer/sdk @metalayer/widget ``` ### EVM + Solana (beta) ```bash pnpm theme={null} pnpm add viem wagmi @tanstack/react-query @solana/web3.js @solana/spl-token @metalayer/sdk @metalayer/widget ``` ```bash npm theme={null} npm install viem wagmi @tanstack/react-query @solana/web3.js @solana/spl-token @metalayer/sdk @metalayer/widget ``` ```bash yarn theme={null} yarn add viem wagmi @tanstack/react-query @solana/web3.js @solana/spl-token @metalayer/sdk @metalayer/widget ``` **Solana support is currently in beta** and not available in mainnet environments. Contact our team to enable Solana bridging for testnet. ## API Key Setup Contact our team to get your API key. ## Basic Usage ```tsx theme={null} import '@metalayer/widget/styles.css'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { WidgetProvider, Widget } from '@metalayer/widget'; import { WagmiProvider, createConfig, http } from 'wagmi'; import { mainnet } from 'wagmi/chains'; const queryClient = new QueryClient(); const wagmiConfig = createConfig({ chains: [mainnet], transports: { [mainnet.id]: http() }, }); function App() { return ( { // Update your wagmi config with the widget's supported chains }} > openWalletModal()} /> ); } ``` > **Note:** The widget requires a `WagmiProvider` from your application. Use > `onSupportedChainsLoad` to update your wagmi config with the chains the widget supports. # Migration Guide Source: https://docs.caldera.xyz/metalayer/widget/migration Upgrade from @metalayer/widget v0.x to v1.x This guide helps you upgrade from `@metalayer/widget` v0.x to v1.x, which introduces a cleaner API, improved naming conventions, and a powerful new theme system. ## Breaking Changes ### 1. External WagmiProvider Required (disableWagmi removed) The widget no longer ships an internal `WagmiProvider`. The `disableWagmi` prop has been removed — you **must** provide your own `WagmiProvider` in your application. If you were already using `disableWagmi={true}`, simply remove the prop: ```diff theme={null} ``` If you were relying on the widget's internal `WagmiProvider` (the old default), wrap your app with your own: ```diff theme={null} + { + // Update wagmi config with supported chains + }} > + ``` Use `onSupportedChainsLoad` to update your wagmi config with the chains the widget supports. ### 2. Widget Props Structure The widget no longer uses a nested `config` object. Props are now passed directly to the component. ```tsx Before (v0.x) theme={null} ``` ```tsx After (v1.x) theme={null} ``` ### 3. Callback Naming Changes All callbacks have been renamed for clarity and consistency with React conventions: | Old Name (v0.x) | New Name (v1.x) | Description | | --------------------- | ------------------------ | ----------------------------------- | | `onOpenConnectModal` | `onConnectClick` | Handler when user clicks connect | | `onDisconnectWallet` | `onDisconnectClick` | Handler when user clicks disconnect | | `onSubmitTransaction` | `onTransactionSubmitted` | Fired after transaction submission | | `onSelectToken` | `onTokenSelected` | Fired after token selection | ### 4. Theme System The `brandColor` prop has been **removed** in favor of the new comprehensive theme system. ```tsx Before (v0.x) theme={null} ``` ```tsx After (v1.x) theme={null} ``` **Note:** `brandColor` has been completely removed in v1.x. You must use the new `theme` prop. See the [New Theme System Features](#new-theme-system-features) section below for comprehensive theming options. ### 5. WidgetProvider Props Update The `chains` prop has been renamed to `enabledChains` for clarity: ```tsx Before (v0.x) theme={null} ``` ```tsx After (v1.x) theme={null} ``` ### 6. RPC / wagmi transports (Metalayer RPC helpers) v1.x expects you to own **`WagmiProvider`** and therefore your **transports**. Using plain viem **`http()`** (or other defaults that ignore Metalayer metadata) does **not** use Metalayer’s ordered RPCs or **`alternativeRpcs`** as viem **`fallback`** endpoints, which can lead to rate limits or mismatches with the chains the widget loads. Prefer: * **`createWidgetClient`** with wagmi **`createConfig`** using a **`client({ chain }) { return createWidgetClient(chain) }`** callback, typically **`multiInjectedProviderDiscovery: false`**, after converting `onSupportedChainsLoad` chains with **`chainsToViemChains`** / **`chainToViemChain`** (see [Components](/metalayer/widget/components#wagmi-client-callback)), or * **`createWidgetTransportsRecord(viemChains)`** with **`createConfig({ chains, transports })`** or RainbowKit **`getDefaultConfig({ transports })`**. ```diff theme={null} - transports: { [chain.id]: http() }, + transports: createWidgetTransportsRecord(viemChains), ``` ## Step-by-Step Migration ### Step 1: Update Package Version ```bash pnpm theme={null} pnpm update @metalayer/widget@^1.0.0 ``` ```bash npm theme={null} npm update @metalayer/widget@^1.0.0 ``` ```bash yarn theme={null} yarn upgrade @metalayer/widget@^1.0.0 ``` ### Step 2: Update Widget Component Usage Find all `` components and update the props: ```diff theme={null} - disconnect(), - onSubmitTransaction: (source, dest, amount) => { - console.log('Transaction submitted', { source, dest, amount }); - }, - className: 'rounded-xl', - }} - /> + disconnect()} + onTransactionSubmitted={(source, dest, amount) => { + console.log('Transaction submitted', { source, dest, amount }); + }} + className="rounded-xl" + /> ``` ### Step 3: Update WidgetProvider Theme Replace `brandColor` with the new theme configuration: ```diff theme={null} ``` ### Step 4: Update Token Selection Callbacks If you're using token selection callbacks, update the naming: ```diff theme={null} { - console.log('Token selected', { direction, chainId, tokenAddress }); - } - }} + onTokenSelected={(direction, chainId, tokenAddress) => { + console.log('Token selected', { direction, chainId, tokenAddress }); + }} /> ``` ### Step 5: Update Controlled Token Selection If using controlled source/destination props: ```diff theme={null} ``` ## New Theme System Features Take advantage of the new theming capabilities: ### Predefined Themes ```tsx theme={null} ``` ### Custom Color Palette ```tsx theme={null} ``` ### Feature Toggles ```tsx theme={null} ``` ### Advanced Overrides ```tsx theme={null} ``` ## Common Integration Updates ### RainbowKit ```diff theme={null} function BridgePage() { const { openConnectModal } = useConnectModal(); const { disconnect } = useDisconnect(); return ( ); } ``` ### Dynamic.xyz ```diff theme={null} function BridgePage() { const { setShowAuthFlow } = useDynamicContext(); return ( setShowAuthFlow(true), - }} + onConnectClick={() => setShowAuthFlow(true)} /> ); } ``` ### ConnectKit ```diff theme={null} function BridgePage() { const { openConnectModal } = useModal(); const { disconnect } = useDisconnect(); return ( ); } ``` ## TypeScript Updates The type definitions have changed significantly: ```typescript theme={null} // Old types (v0.x) import type { WidgetProps, WidgetConfig } from '@metalayer/widget'; // v0.x used nested config object const props: WidgetProps = { config: { onOpenConnectModal: () => void, onDisconnectWallet?: () => void, onSubmitTransaction?: (sourceChainId?: number, destChainId?: number, amount?: string) => void, onSelectToken?: (direction: 'source' | 'destination', chainId: number, tokenAddress: string) => void, className?: string, source?: { chainId: number; tokenAddress?: string }, destination?: { chainId: number; tokenAddress?: string }, } }; // New types (v1.x) import type { WidgetProps } from '@metalayer/widget'; const props: WidgetProps = { // REQUIRED callback onConnectClick: () => void, // Optional callbacks onDisconnectClick?: () => void, onTransactionSubmitted?: ( sourceChainId?: number, destChainId?: number, amount?: string ) => void, onTokenSelected?: ( direction: 'source' | 'destination', chainId: number, tokenAddress: string ) => void, // Optional configuration source?: { chainId: number; tokenAddress?: string }, destination?: { chainId: number; tokenAddress?: string }, className?: string, isConnecting?: boolean, }; ``` ### Additional Exported Types v1.x exports comprehensive TypeScript types for all configuration: ```typescript theme={null} import type { // Widget types WidgetProps, // Provider types WidgetProviderProps, // Theme types ThemeConfig, Theme, ThemeMode, PredefinedTheme, ThemeFeatures, CornerRadiusStyle, ShadowStyle, FontFamilyConfig, GoogleFontsConfig, CustomFontConfig, // Solana types (if using Solana support) WidgetSolanaSigner, WidgetSolanaProps, } from '@metalayer/widget'; ``` ## Troubleshooting Remove the `config` wrapper and pass props directly to ``. Use `theme={{ colors: { primary: 'your-color' } }}` instead. Rename to `onConnectClick`. Rename to `onTokenSelected`. ## Best Practices 1. **Use the new theme system** - It provides better customization and consistency 2. **Leverage TypeScript** - The new types provide better autocomplete and type safety 3. **Optional disconnect** - Only provide `onDisconnectClick` if your wallet library supports it 4. **Test callbacks** - Ensure all renamed callbacks are working correctly after migration # Theming Source: https://docs.caldera.xyz/metalayer/widget/theming Customize the appearance of the Metalayer Bridge Widget ## Overview The Metalayer Bridge Widget offers extensive theming capabilities to match your application's design. You can use predefined themes for quick setup or customize every aspect of the widget's appearance. ### Widget Properties | Property | Type | Description | | ------------ | -------------------------------------------------------- | ------------------------------- | | `predefined` | `'comfy' \| 'modern'` | Use a predefined theme | | `mode` | `'light' \| 'dark'` | Color mode | | `colors` | **[ThemeColors](#available-palettes)** | Custom color palette | | `corners` | `'none' \| 'minimal' \| 'soft' \| 'medium' \| 'rounded'` | Border radius style | | `shadow` | `'none' \| 'sharp' \| 'light' \| 'heavy'` | Shadow style | | `features` | **[ThemeFeatures](#widget-features)** | Feature toggles | | `fontFamily` | **[FontFamily](#fontfamily)** | Font family configuration | | `fonts` | **[FontsConfig](#fontsconfig)** | Font loading configuration | | `overrides` | `Partial<`**[Theme](#theme-object-structure)**`>` | Direct theme property overrides | ## Color Palette Using a single Hex color, the widget will generate a color palette for the widget. Custom Brand Color Preview ```tsx theme={null} ``` ### Available Palettes The color palette properties that can be used to customize the widget. | Property | Type | Description | | --------- | -------- | -------------------------------------- | | `primary` | `string` | Primary brand color (hex format) | | `neutral` | `string` | Neutral/gray color (hex format) | | `success` | `string` | Success state color (hex format) | | `warning` | `string` | Warning state color (hex format) | | `info` | `string` | Info state color (hex format) | | `failure` | `string` | Error/failure state color (hex format) | ## Predefined Themes The widget includes two predefined themes that provide a complete, cohesive look out of the box. ### Comfy Theme The default theme with a warm, approachable aesthetic. Comfy Theme Preview - Light Mode ```tsx theme={null} ``` ### Modern Theme A sleek, contemporary design with sharper edges and a more minimal feel. Modern Theme Preview - Light Mode ```tsx theme={null} ``` ### Dark Mode Enable dark mode on any theme by setting the `mode` property: ```tsx theme={null} ``` ## Font Customization The widget uses three font roles: **label** (headings/labels), **body** (body text), and **data** (numeric/monospace). Default fonts are Inter and Martian Mono. #### Google Fonts Specify font names for auto-loading from Google Fonts: ```tsx theme={null} ``` #### Recommended Fonts by Role | Role | Recommended Google Fonts | | ------- | ------------------------------------------------------------------------------------------------------------------------------ | | `label` | Inter, Montserrat, Fredoka, Oswald, Manrope, Merriweather, Noto Serif Display, Roboto, Jua, Bitcount | | `body` | Inter, Montserrat, Manrope, Merriweather, Noto Serif Display, Roboto, Fredoka, Fira Code, Roboto Mono, Kode Mono, Martian Mono | | `data` | Fira Code, Roboto Mono, Kode Mono, Martian Mono, Roboto, Inter, Montserrat, Manrope | #### Google Fonts with Custom Weights ```tsx theme={null} ``` #### Custom Weight Choices For more control over which font weights are used for regular and bold text, pass an object instead of a string: ```tsx theme={null} ``` **Default weights by role:** | Role | `base` | `bold` | | ----- | ------ | ------ | | label | 700 | - | | body | 400 | - | | data | 500 | 700 | The `bold` weight is currently only supported for the `data` role. Setting `bold` on `label` or `body` will show a dev warning and be ignored. #### Custom Fonts For fonts not on Google Fonts, use `customFonts` with woff2 URLs: ```tsx theme={null} ``` For multiple weights: ```tsx theme={null} fonts: { customFonts: [{ family: 'MyBrandFont', weights: [ { weight: 400, url: 'https://cdn.example.com/mybrand-regular.woff2' }, { weight: 700, url: 'https://cdn.example.com/mybrand-bold.woff2' }, ], }] } ``` #### System Fonts ```tsx theme={null} theme={{ fontFamily: { label: 'system-ui', body: '-apple-system', data: 'ui-monospace', } }} ``` #### FontFamily | Property | Type | Description | | -------- | ---------------------------- | ------------------------------- | | `label` | `string \| FontFamilyConfig` | Font for headings and labels | | `body` | `string \| FontFamilyConfig` | Font for body text | | `data` | `string \| FontFamilyConfig` | Font for numeric/monospace data | #### FontsConfig | Property | Type | Description | | ------------- | ------------------- | ---------------------------------- | | `googleFonts` | `GoogleFontsConfig` | Google Fonts loading configuration | | `customFonts` | `CustomFont[]` | Custom font definitions | #### FontFamilyConfig | Property | Type | Description | | --------- | ---------------------------------- | --------------------------- | | `family` | `string` | Font family name (required) | | `weights` | `{ base?: number; bold?: number }` | Font weight configuration | The `bold` weight in `weights` is only supported for the `data` role. #### GoogleFontsConfig | Property | Type | Description | | ---------- | --------------------------------------------------------- | --------------------------------------------------------------------- | | `families` | `string[]` | Font families with weights (e.g., `'Roboto:wght@400;700'`) (required) | | `display` | `'auto' \| 'block' \| 'swap' \| 'fallback' \| 'optional'` | Font display strategy | #### CustomFont | Property | Type | Description | | --------- | ----------------------------------- | ---------------------------------------------- | | `family` | `string` | Font family name (required) | | `url` | `string` | Single woff2 font URL (weight defaults to 400) | | `weights` | `{ weight: number; url: string }[]` | Multiple weight definitions | Either `url` or `weights` must be provided for custom fonts. ## Widget Features Toggle specific visual features of the widget on or off. | Property | Type | Description | | ------------------- | --------- | ----------------------- | | `headerIcons` | `boolean` | Show header icons | | `headerBackground` | `boolean` | Show header background | | `background` | `boolean` | Show widget background | | `outlineComponents` | `boolean` | Show component outlines | ```tsx theme={null} ``` ## Advanced Overrides For complete control, use the `overrides` property to customize specific theme values. This allows you to override any part of the generated theme. ```tsx theme={null} ``` These types are used when customizing advanced theme overrides. #### StatusColors There are 4 types of statuses: info, warning, success, and failure. | Property | Type | Description | | ------------ | -------- | ------------------------------------------- | | `main` | `string` | Main status color (hex format) | | `foreground` | `string` | Text color for status elements (hex format) | | `light` | `string` | Lighter variant (hex format) | | `dark` | `string` | Darker variant (hex format) | #### InteractiveColors | Property | Type | Description | | ---------- | -------- | ----------------------------------------- | | `active` | `string` | Color when element is active (hex format) | | `hover` | `string` | Color on hover (hex format) | | `inactive` | `string` | Color when inactive (hex format) | | `disabled` | `string` | Color when disabled (hex format) | | `contrast` | `string` | Contrasting text/icon color (hex format) | #### InteractiveThemeColors | Property | Type | Description | | ----------- | ---------------------------------------- | -------------------------------------- | | `primary` | `InteractiveColors` | Primary interactive element colors | | `secondary` | `InteractiveColors` | Secondary interactive element colors | | `tertiary` | `InteractiveColors` | Tertiary interactive element colors | | `input` | `{ active?: string; inactive?: string }` | Input field border colors (hex format) | #### Theme Object Structure The complete theme object structure for advanced overrides. All properties are optional. | Property | Type | Description | | ------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------- | | `brand` | `string` | Brand accent color (hex format) | | `background` | `{ main?: string; layer1?: string; layer2?: string; layer3?: string }` | Background colors for elevation layers | | `text` | `{ primary?: string; secondary?: string; disabled?: string }` | Text colors | | `interactive` | `InteractiveThemeColors` | Interactive element colors | | `status` | `StatusColors` | Status indication colors (info, warning, success, failure) | | `misc` | `{ divider?: string; footer?: string; skeleton?: string; highlight?: string }` | Miscellaneous UI colors | | `shadows` | `{ bottom?: string; around?: string }` | Shadow CSS values | All color values should be provided in hex format (e.g., `#RRGGBB` or `#RGB`). # What are Rollups? Source: https://docs.caldera.xyz/rollup-engine/about/about-rollups Rollups are a Layer 2 scaling solution designed to enhance the scalability and efficiency of blockchain networks. In short: rollups are blockchains that rely on another layer-one blockchain (especially Ethereum) for settlement, while providing better scalability and performance guarantees compared to the underlying blockchain. Here's a breakdown: ### Bundling Transactions Rollups work by aggregating or "rolling up" multiple transactions into a singular transaction or a batch. This process occurs on a separate Layer 2 blockchain, which is a secondary framework built atop the primary (Layer 1) blockchain​. ### Off-chain Execution The execution of transactions is performed off-chain in rollups, thereby reducing the data that needs to be posted to the main blockchain. This is particularly beneficial in congested blockchain networks where the high volume of transactions can lead to slower processing times and higher fees. ### Posting to Layer 1 Once the transactions have been bundled and executed off-chain, a single transaction or a summary of the batch is posted to the main (Layer 1) blockchain. This action retains the security features of the primary blockchain while significantly reducing the data load, as only the rolled-up transaction is recorded on-chain​. # Optimistic Rollups You can deploy [Arbitrum Nitro](/about/nitro) and [OP Stack](/about/bedrock) rollups via Caldera -- both of these stacks are "Optimistic" rollups. The term "optimistic" in Optimistic Rollups comes from the optimistic assumption that transactions within a rollup are valid. In the "happy path" where the rollup is acting honestly, no on-chain proof of correctness is required. However, if the rollup sequencer acts maliciously or errantly, a "fault proof" can be submitted to the L1 and prevent incorrect execution from occuring. Want to learn more about Optimistic Rollups? View [this article](https://ethereum.org/en/developers/docs/scaling/optimistic-rollups) from ethereum.org # Zero-Knowledge Rollups You can deploy [ZK Stack](/about/zksync) and [Polygon CDK](/about/polygon) rollups via Caldera as well -- both of these stacks are "Zero-Knowledge" (aka ZK) rollups. In contrast to optimistic rollups, ZK rollup nodes must submit a validity proof for verification to update state. The validity proof is a cryptographic assurance that the state-change proposed by the rollup is really the result of executing the given batch of transactions. This means that ZK-rollups only need to provide validity proofs to finalize transactions on Ethereum instead of posting all transaction data on-chain like optimistic rollups. To learn more about ZK Rollups, view [this article](https://ethereum.org/en/developers/docs/scaling/zk-rollups/) from ethereum.org # Alternative Data Availability Source: https://docs.caldera.xyz/rollup-engine/about/alternative-da This is a beta feature. Want to get started? [Get in touch](https://calendly.com/james_caldera/30min?utm_source=doc). Caldera supports Alternative Data Availability (Alt-DA) via integrations with [Celestia](https://docs.celestia.org/learn/how-celestia-works/data-availability-layer), [Near](https://near.org/data-availability), and [Arbitrum Anytrust](https://arbitrum.io/anytrust) # Why Alternative DA? In order to ensure invalid transactions processed can be caught and reverted on a rollup, users need a way to make sure that the rollup's block data is actually published. Right now, the vast majority of Ethereum rollups solve this by simply posting all of the rollup blocks onto Ethereum and relying on it for data availability. But, traditional Ethereum DA can lead to extremely high and volatile costs, as rollups are forced to compete for limited blockspace with all other dApps and users transacting on Ethereum. As a result, over 95% of the cost of a rollup transaction today comes from posting data to Ethereum. # How it Works Check out [our blog post](https://blog.caldera.xyz/alternative-data-availibility-for-approllups/) for an in-depth explanation Alternative DA systems use innovative approaches to separate out data availability from a chain's settlement, dramatically lowering associated costs and increasing throughput to significantly improve rollups' long-term scalability. At the moment, we're proud to offer Celestia and Near as our current Alt-DA solutions for all Caldera Chains (and plan to integrate with other Alt-DA providers in the future), leveraging their novel technologies to save significant costs for the chains in our ecosystem. ![Celestia Diagram](https://docs.celestia.org/img/learn/monolithic-modular.png) # Build with Alternative DA We're excited to work with teams exploring rollups with alternative data availability. If you're interested, please [get in touch](https://calendly.com/james_caldera/30min?utm_source=doc)! # Optimism Bedrock Source: https://docs.caldera.xyz/rollup-engine/about/bedrock For a closer look, check out [Optimism's Documentation](https://stack.optimism.io/) With Caldera, you can deploy dedicated rollups using the **OP stack** (Optimism Bedrock). The OP stack is a battle-tested Optimistic Rollup stack. The OP stack powers *Optimism Mainnet* and *Base*, Coinbase's recently-launched L2. Collectively, the OP stack secures over \$3.5 Billion in TVL. ### Benefits * 10-100x cheaper transactions compared to Ethereum. * Ethereum equivalence, with full support for Ethereum smart contracts and developer tooling * Fast block times (2s per block) * Optional support for further cost reduction via Celestia DA * Extremely permissive (MIT) licensing * Ability to opt into the [Superchain](https://stack.optimism.io/docs/understand/explainer/), Optimism's future network of chains that share bridging, governance, and interoperability # The Superchain For more info, view the Superchain explainer [here](https://stack.optimism.io/docs/understand/explainer/) The Optimism Superchain is envisioned as a network of interconnected chains on the Optimism protocol, enhancing scalability and interoperability among Layer 2 blockchain networks. The Superchain aims to unify the Optimism Mainnet and other OP stack chains into a single connected network, facilitating shared features like bridging, decentralized governance, and a communication layer. This setup is designed to allow individual chains to operate cohesively, promoting seamless communication and transactions among them. The Superchain design is still early. We recommend consulting Optimism's documentation for the most up-to-date design. # Guardian Nodes Source: https://docs.caldera.xyz/rollup-engine/about/guardian-node Caldera’s Guardian Node system introduces the first production-ready system where third parties are able to verify rollup blocks in exchange for rewards. This system introduces a novel “light verifier” for Arbitrum rollups which allows Guardian Node operators to verify Nitro batches on everyday hardware without needing to run a full Arbitrum node. By focusing on reducing barriers to verify the network and distributing incentives, Caldera’s Guardian Node system improves the resilience and security of Arbitrum rollups. ## The Benefits 1. **Revenue Source**: A significant go-to-market benefit is that a project can use Guardian Nodes as a source of revenue. HYCHAIN, which launched its Guardian Node system with Caldera’s tooling, sold \~16k node keys within 2 weeks, raising \~2000 ETH. The sale period will continue for a duration of 3 years which will provide a steady revenue stream. 2. **Decentralization**: EVM rollups have all but solved the scalability problem, with L2s and L3s on Ethereum enabling virtually infinite scale. But previously, there was still no incentive for honest network participants to monitor these rollups. Guardian Nodes allow teams to decentralize their rollups by enabling users to verify blocks and secure the network in exchange for rewards. 3. **Token Demand**: By enabling more parties to watch over a rollup and identify malicious behavior, the network’s security grows more robust— a crucial step to establishing trust in the chain’s correctness. This in turn generates more demand for a rollup’s native token, which is required for users to participate in validation and helps provide practical cryptoeconomic security for the network. # Native Gas Token Source: https://docs.caldera.xyz/rollup-engine/about/native-token With Caldera Chains, you can deploy Arbitrum and ZKsync rollups with a custom native gas token. ### What tokens can I use? You can use almost any `ERC-20` token. as your rollup's native token. This includes your protocol tokens, or stablecoins such as USDC or DAI. The only tokens that cannot be used as rollup native tokens are [elastic tokens](https://academy.binance.com/en/articles/elastic-supply-tokens-explained) due to their volatile supply. Thankfully, very few tokens employ this type of design. It is a [requirement](https://docs.arbitrum.io/launch-arbitrum-chain/configure-your-chain/common-configurations/use-a-custom-gas-token-rollup#requirements-of-the-custom-gas-token) that your native gas token is a standard `ERC-20` token. # Arbitrum Nitro Source: https://docs.caldera.xyz/rollup-engine/about/nitro For a closer look, check out [Arbitrum's Documentation](https://docs.arbitrum.io/inside-arbitrum-nitro) With Caldera, you can deploy dedicated rollups using the **Arbitrum Nitro** stack. Arbitrum Nitro is a battle-tested Optimistic Rollup stack. Arbitrum Nitro powers *Arbitrum One*, the flagship Arbitrum chain, and *Arbitrum Nova*, a lower-cost chain targeted towards gaming. Arbitrum Nitro secures over \$6 Billion in TVL across chains in production. ### Benefits * 10-100x cheaper transactions compared to Ethereum. * Ethereum equivalence, with full support for Ethereum smart contracts and developer tooling * Faster block times, as fast as 250ms when under high throughput * Working fault proofs * Optional Support for WASM smart contracts via Stylus * Support for further cost reduction via Arbitrum Anytrust or Celestia DA * Ability to choose your rollup's native token # Anytrust For more info, view the Anytrust docs [here](https://docs.arbitrum.io/inside-arbitrum-nitro/#inside-anytrust) Arbitrum AnyTrust, a variant of Arbitrum Nitro technology, adopts a mild trust assumption to lower transaction costs. Unlike standard Arbitrum where all nodes require access to every Layer 2 transaction data, AnyTrust relies on a Data Availability Committee (DAC) to store and provide data on demand, assuming at least two members are trustworthy for data availability. It employs Data Availability Certificates (DACerts) to guarantee data availability until a specified expiration time. With Anytrust, you can achieve a further **10-100x** cost decrease compared to a standard rollup. This setup allows for more cost-effective transaction processing while ensuring data availability, aiding in creating personal AnyTrust and Rollup chains with an infrastructure capable of significantly higher capacity than Ethereum, yet still leveraging Ethereum's security framework. # Stylus For more info, view the Stylus docs [here](https://docs.arbitrum.io/stylus/stylus-gentle-introduction) Arbitrum Stylus is an advancement to the Arbitrum Nitro technology, introducing a secondary, co-equal WASM virtual machine alongside the existing Ethereum Virtual Machine (EVM) on the Arbitrum chains like Arbitrum One, Arbitrum Nova, and Arbitrum Orbit. This new virtual machine enhances the programming environment, enabling developers to write and deploy smart contracts using languages like Rust, C, or C++. WASM execution is significantly more performant (Over **10x less gas used**) and allows developers to use battle-tested Rust, C++, and C libraries in their smart contracts. Check out the OffchainLabs/*Awesome-Stylus* repo on Github for examples of smart contracts with Stylus # Reliability Source: https://docs.caldera.xyz/rollup-engine/about/reliability ### Uptime SLAs For all mainnet deployments, Caldera offers a 99.99% uptime SLA. ### Industry Standard Best Practices At Caldera, we employ industry-standard best practices to ensure the reliability and availability of our services. Our Kubernetes configurations are designed with a high availability setup to mitigate service disruptions and maintain a resilient infrastructure. By adhering to recognized standards and best practices, we are able to provide a robust and reliable environment for our operations and, by extension, our partners. All Caldera infrastructure is hosted in Amazon Web Services, and split across multiple regions. Our Kubernetes configuration is designed with reliability in mind: we auto-failover in the case of sequencers going down, and we autoscale our infra when traffic spikes. ### L1 RPC Fallback One of the "weak links" in rollup operation is the connection to a layer-one (Ethereum mainnet) full node. If this connection is severed for an extended period of time, the rollup cannot function properly. To further bolster our reliability, we have established a proxy load-balancing service to derisk potential challenges posed by L1 RPC outages. This proxy service aggregates over multiple top RPC providers, and re-routes our traffic in the event of downtime. This layer of protection helps in maintaining uninterrupted service and ensuring that our systems remain accessible and functional even during external disruptions in the broader network. ### Transparent Status Page status page We believe in full transparency when it comes to system performance and availability. Every mainnet deployment comes with a status page, powered by [Betterstack](https://betterstack.com). Our status page provides real-time updates on each rollup, allowing you to subscribe and stay informed about the operational status of our services. In the event of downtime, all members of the Caldera engineering team are alerted. ### Response SLAs and Escalation Procedures Timely response and resolution are crucial for maintaining a high level of service reliability. We have defined Service Level Agreements (SLAs) to ensure prompt responses to incidents and issues, **24 hours a day, 7 days a week**. Our SLAs outline the expected response times and resolution procedures, providing a clear framework for addressing concerns. Additionally, we have an escalation procedure in place for operational and arbitration scenarios, ensuring that critical issues receive the necessary attention and are resolved expediently. # Security Source: https://docs.caldera.xyz/rollup-engine/about/security ### Multisig Ownership of Mainnet Rollup Contracts Security is paramount when dealing with blockchain contracts, especially when customer funds are involved. At Caldera, we employ multi-signature (multisig) ownership for our mainnet rollup contracts. This means that multiple signatures are required to authorize any significant actions, providing an additional layer of security. With multisig ownership, **we ensure that customer funds remain protected, even in the unlikely event that our systems are compromised**. ### Using battle-tested, audited rollup stacks Caldera only runs the most battle-tested rollup stacks, including Optimism, Arbitrum, and the Polygon CDK. Each of these stacks secures millions to billions of dollars in value, on production mainnets. ### Dual Authorization for Production Infrastructure Access All Caldera production infrastructure is locked under a dual-authorization scheme. This process mandates that no single individual can access or modify the production environment without a second person from the company signing off on the action. This dual authorization ensures that there are checks and balances in place, significantly reducing the risk of unauthorized or malicious activity within our production infrastructure. # Decentralized Sequencing Source: https://docs.caldera.xyz/rollup-engine/about/shared-sequencing This is a beta feature. Want to get started? [Get in touch](https://calendly.com/james_caldera/30min?utm_source=doc). Caldera supports Decentralized Sequencing via an integration with [Espresso](https://www.espressosys.com/), a premier decentralized sequencing network. # Why Decentralized Sequencing? Every rollup relies on a sequencer to order and verify the transactions on the chain. Traditionally, these sequencers have been centralized entities, controlled by a single party or group of parties. The vast majority of rollups currently in production (including Arbitrum One, Optimism mainnet, Base, and zkSync, among others) currently utilize a centralized sequencer. These rollups are still able to inherit the security properties of their underlying chain via rollup proof systems, but their centralized sequencers still pose several problems: * Centralized sequencers create a single point of failure in the system. If the sequencer goes down, it can become impossible or prohibitively expensive to submit transactions for inclusion * The centralized sequencer can arbitrarily censor or delay transactions, or reorder transactions to extract MEV * Users do not have visibility into how transactions are ordered The status quo requires users to place some trust in rollup operators: users must trust that the operator will keep the sequencer online, trust that the sequencer orders transactions according to spec, and trust that the operator is not extracting MEV from the chain or arbitrarily censoring transactions. # How it Works Check out [Espresso's documentation](https://docs.espressosys.com/sequencer/releases/cortado-testnet-release/op-stack-integration) for an in-depth explanation At a high level, the Espresso Sequencer network replaces the rollup's mempool implementation. User transactions are sent to the Espresso Sequencer rather than the rollup node itself. Then, rollup nodes query sequenced transactions from Espresso's sequencer node. This eliminates the dependence on a centralized sequencer to act fairly. ![Espresso Sequencer Diagram](https://3457829372-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBeiHaL4yXVSdD2dUzh9N%2Fuploads%2F6NYf3f60ffI3qN3t8vWO%2Fsequence-gitbook.drawio.svg?alt=media\&token=6b7b36e2-5d69-46c3-8e2b-0caf4066fcaf) # Integrate with Espresso We're excited to work with teams exploring rollups with decentralized sequencing. Please [get in touch](https://calendly.com/james_caldera/30min?utm_source=doc)! # Bridged USDC Source: https://docs.caldera.xyz/rollup-engine/about/usdc Leverage Circle's Bridged USDC Standard for [OP Bedrock](/about/bedrock) and [Arbitrum Nitro](/about/nitro.mdx) rollups with Caldera. Bridged USDC provides benefits for blockchains, developers, and users alike, catalyzing activity on new blockchain networks and simplifying any future transition to native USDC. ## For Blockchains Get bridged USDC into the hands of developers and users early with the potential for a seamless upgrade to native issuance in the future, thereby avoiding the time-consuming liquidity migration process of educating and incentivizing your ecosystem to move from bridged to native USDC. ## For developers Build on bridged USDC with a contract address that will persist after an upgrade to native, no code change needed. Provide users a way to store, pay, trade, borrow and lend with bridged USDC that automatically becomes native upon an upgrade. No need to swap to a new asset. # ZK Stack Source: https://docs.caldera.xyz/rollup-engine/about/zksync Full ZK Stack support is here! If you're interested in deploying a ZK Stack hyperchain with Caldera today, [contact us](https://calendly.com/james_caldera/30min?utm_source=docs)! The ZK Stack is a modular, open-source framework designed to build custom ZK-powered hyperchains leveraging zkSync infrastructure. At its core, the ZK Stack offers two key features: sovereignty and seamless connectivity. Each ZK Stack hyperchain operates completely independently, relying solely on Ethereum L1 for their liveness and security, while supporting a shared bridge to facilitate the interconnection of every hyperchain, thereby enabling trustless, fast (within minutes), and inexpensive (cost of a single transaction) interoperability. ### Benefits * Ultra-low gas fees compared to Ethereum. * Ethereum compatibility, with full support for Ethereum smart contracts and developer tooling * Native account abstraction * Native cross-chain composability via hyperbridges * Support for further cost reduction via alternative DA solutions * Ability to choose your rollup's native token # Hyperchains For more info, view zkSync's hyperchain docs [here](https://docs.zksync.io/zk-stack/concepts/hyperchains-hyperscaling.html) Hyperchains are fractal-like instances of zkEVM running in parallel and with common settlement on the L1 mainnet. The name Hyperbridge comes from the traditional web, where users can navigate websites seamlessly using hyperlinks. Similarly, ZK Stack rollups are connected seamlessly via Hyperbridges. Each Hyperchain is powered by the same zkEVM engine available on the ZK Stack (and currently powering the first hyperchain, zkSync Era). All the ZKP circuits thus remain 100% identical, allowing Hyperchains to fully inherit their security from the L1 regardless of deployer, which ensures zero additional trust/security assumptions. Hyperchain Diagram # Foundry Source: https://docs.caldera.xyz/rollup-engine/deploying-contracts/foundry Deploying Smart Contracts using Foundry ## What is Foundry? Foundry is a toolset for Ethereum development written in Rust that assists developers in managing dependencies, compiling projects, running tests, deploying contracts, and interacting with blockchains through the command line interface. Additionally, Foundry can directly communicate with Caldera's Ethereum API, enabling the use of Foundry to deploy smart contracts into the Caldera network. ## Get Started with Foundry 1. Install Foundry * Linux or MaxOS ``` curl -L https://foundry.paradigm.xyz | bash foundryup ``` * Windows ``` curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs/ | sh cargo install --git https://github.com/foundry-rs/foundry foundry-cli anvil --bins --locked ``` 2. Create a project ``` forge init foundry ``` 3. Navigate to the Source in the project and create your smart contract ``` cd src touch MyToken.sol ``` 4. Input your smart contract or use the sample contract below. ```solidity theme={null} // SPDX-License-Identifier: MIT // compiler version must be greater than or equal to 0.8.17 and less than 0.9.0 pragma solidity ^0.8.17; contract HelloWorld { string public greet = "Hello World!"; } ``` 5. Install OpenZeppelin contracts as a dependency ``` forge install OpenZeppelin/openzeppelin-contracts ``` 6. Compile contract ``` forge build ``` ## Deploying Your Smart Contract Deploying a contract with Forge is a simple process that can be done with a single command. However, it requires an RPC endpoint, a private key that has funds, and any arguments for the constructor of the contract. For example, the `MyToken.sol` contract requires an initial supply of tokens to be specified in its constructor, so the command to deploy it on a network will include the argument of 100. To deploy the `MyToken.sol` contract, use the command that corresponds to the Caldera chain's RPC URL while running the `forge create` command: ``` forge create --rpc-url "RPC URL" //Insert your RPC URL here --constructor-args 100 \ --private-key YOUR_PRIVATE_KEY \ src/MyToken.sol:MyToken ``` # Hardhat Source: https://docs.caldera.xyz/rollup-engine/deploying-contracts/hardhat Deploying Smart Contracts using Hardhat ## What is Hardhat? Hardhat is a development environment for Ethereum that helps developers manage and automate the common tasks involved in building smart contracts and decentralized applications. It can directly interact with Caldera's Ethereum API, allowing for the deployment of smart contracts into the Caldera network. Additionally, Hardhat is a comprehensive set of tools for creating Ethereum-based software, which includes various components that aid in editing, compiling, debugging, and deploying smart contracts and decentralized applications. All of these components work together to create a complete development environment. ## Creating a Hardhat Project 1. Create a directory for your project: ``` mkdir hardhat && cd hardhat ``` 2. Initialize the project, which will create a `package.json` file ``` npm init -y ``` 3. Install Hardhat ``` npm install hardhat ``` 4. Create a project ``` npx hardhat ``` 5. Create an empty `hardhat.config.js` and install the Ethers plugin to use the Ethers.js library to interact with the network. ``` npm install @nomiclabs/hardhat-ethers ethers ``` ## Creating Your Smart Contract 1. Create a `contracts` directory ``` mkdir contracts && cd contracts ``` 2. Create `your_contract.sol` file in `contracts` directory ``` touch your_contract.sol ``` ## Creating Your Configuration File Modify the Hardhat configuration file and create a secure file to store your private key in. 1. Create a `secrets.json` file to store your private key ``` touch secrets.json ``` 2. Add your private key to `secrets.json` ``` { "privateKey": "YOUR-PRIVATE-KEY-HERE" } ``` 3. Add the file to your project's `.gitignore`, and never reveal your private key. 4. Modify the `hardhat.config.js` file * Import the Ethers.js plugin * Import the `secrets.json` file * Inside the `module.exports` add the Caldera network configuration ```javascript hardhat.config.js theme={null} require('@nomiclabs/hardhat-ethers'); const { privateKey } = require('./secrets.json'); module.exports = { solidity: "0.8.1", defaultNetwork: "rinkeby", networks: { rinkeby: { url: "https://eth-rinkeby.alchemyapi.io/v2/123abc123abc123abc123abc123abcde", accounts: [privateKey] }, caldera: { url: "RPC URL", // Insert your RPC URL Here } }, } ``` ## Deploying Your Smart Contract 1. Compile the contract ``` npx hardhat compile ``` 2. Create a new directory for the script and name it scripts and add a new file to it called `deploy.js` ``` mkdir scripts && cd scripts touch deploy.js ``` 3. Create a deployment script, like the one below ```javascript scripts/deploy.js theme={null} async function main() { // 1. Get the contract to deploy const Your_Contract = await ethers.getContractFactory('your_contract'); console.log('Deploying Your_Contract...'); // 2. Instantiating a new smart contract const your_contract = await Your_Contract.deploy(); // 3. Waiting for the deployment to resolve await your_contract.deployed(); // 4. Use the contract instance to get the contract address console.log('Your_Contract deployed to:', your_contract.address); } main() .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); }); ``` 4. Deploy `your_contract.sol` using the command below ``` npx hardhat run scripts/deploy.js --network caldera ``` # Remix Source: https://docs.caldera.xyz/rollup-engine/deploying-contracts/remix Deploying Smart Contracts using Remix ## What is Remix? Remix Project is a robust set of tools that can be used by individuals of any skill level throughout the entire process of developing contracts, and it also serves as an educational platform for learning and experimenting with Ethereum. ## Getting Started with Remix 1. Visit Remix to get started. 2. Under **Featured Plugins**, select **Solidity**. 3. Navigate to the **File Explorer** and click "**+**" to create a Smart Contract 4. Input your smart contract or use the sample contract below. ```solidity theme={null} // SPDX-License-Identifier: MIT // compiler version must be greater than or equal to 0.8.17 and less than 0.9.0 pragma solidity ^0.8.17; contract HelloWorld { string public greet = "Hello World!"; } ``` 5. Navigate to the **Compile** sidebar option and click Compile. ## Deploying Your Smart Contract Once you have written your Smart Contract in Remix, you can navigate to the sidebar option to Compile your contract. 1. Change the top **ENVIRONMENT** dropdown from "**Javascript**" to "**Injected Web3**" 2. This will take you MetaMask - Press connect in Metamask to allow Remix access. 3. Add your network to Metamask using these parameters from your Caldera Chain: * Network * New RPC URL * Chain ID * Currency Symbol * Block Explorer URL # Quickstart Source: https://docs.caldera.xyz/rollup-engine/quickstart Get started deploying a dedicated rollup, hosted by Caldera ## Testnet To get started with a testnet environment, head to our dashboard and follow these steps: 1. Sign up or log in through the authorization page 2. Click "Get Started" from the **Manage Rollups** page deployment page 3. Select your rollup framework of choice ([Arbitrum Nitro](/about/nitro), [Optimism Bedrock](./about/bedrock), [zkSync's ZK Stack](./about/zkSync)), and then choose the *Testnet* network type on our **Deploy New Rollup** page newdeploy 4. Select a native gas token and set relevant identifiers (Rollup Name, Subdomain, Chain ID) 5. Click the "Deploy New Rollup" button to launch your testnet rollup! ## Mainnet 1. [Book a demo](https://calendly.com/james_caldera/30min?utm_source=docs) to chat about your project's needs and why you're considering an app-rollup -- we'll brainstorm ways that we can help 2. Caldera will launch a rollup for you with the framework of your choice (Arbitrum Nitro, Optimism Bedrock, ZK Stack), and the parameters of your choice, on the chain of your choice (Ethereum, Polygon, Cronos, Optimism, Arbitrum, etc.) 3. Integrate your app with Caldera. Usually, it takes less than half an hour to port Ethereum apps to a Caldera chain. We're happy to help with this! 4. We'll let you know when your production-grade Mainnet rollup goes live! # Block Explorer Source: https://docs.caldera.xyz/rollup-engine/tools/block-explorer Every Caldera Chain comes equipped with a user-friendly **Block Explorer** that allows for easy viewing of important data such as: * Address balances * Transaction history * Verified contracts * Smart contract code and execution * Network statistics * Mining information Just search for an an address, token symbol, name, transaction hash, or block number to retrieve the on-chain information you're looking for. Additionally, the block explorer's theme and styling can also be customized (through our integration with [Blockscout](https://www.blockscout.com/)) upon request to better fit the preferences of your users. Block Explorer The explorer provides a valuable tool for both users and developers looking to better understand and interact with a blockchain, providing transparency and accessibility to the inner workings of a blockchain. It can be used for a variety of purposes such as tracking transactions, monitoring smart contract execution, and analyzing network activity. # Bridge UI Source: https://docs.caldera.xyz/rollup-engine/tools/bridge-ui Each Caldera Chain comes automatically deployed with a corresponding web-based **Bridge User Interface** that enables developers and users to deposit and withdraw assets to/from your Caldera Chain. Our Bridge UI offers: * Customizable branding, colors, and text copy on a per-rollup basis * Seamless transfer of assets between your Caldera Chain and various public blockchains * Clear, user-friendly interface Bridge UI ## What is a bridge? A crypto bridge is a mechanism that allows for the transfer of assets between different blockchain networks. This user-facing interface allows end-users to easily interact with the bridge and bring liquidity onto your rollup. # Testnet Faucet Source: https://docs.caldera.xyz/rollup-engine/tools/faucet Caldera Chains come equipped a built-in **Testnet Faucet** that allows users to easily request, acquire, and test with the chain's native cryptocurrency token. This feature is designed to make it easy for developers, testers, and new users to obtain small amounts of the native token to explore the functionality and features of the blockchain. The faucet feature is typically configured to dispense small amounts of cryptocurrency to users who request it, allowing developers to test the functionality of the chain without having to make a purchase and incurr any financial risk. Additionally, faucets can serve as a useful tool for new testnet users to onboard onto your ecosystem and familiarize themselves with the fundamental functionality of your chain. Testnet Faucet # Hub Page Source: https://docs.caldera.xyz/rollup-engine/tools/hub-page Caldera Chains all come with shareable **Hub Page** for both internal and external use, which provides one unified place to access all essential user-facing tooling, including: * Chain Details * [Block Explorer](../tools/block-explorer) * [Bridge UI](../tools/bridge-ui) * [Testnet Faucet](../tools/faucet) * Documentation Hub Page Image # Whitelabel Docs Source: https://docs.caldera.xyz/rollup-engine/tools/whitelabel-docs Each team building a Caldera Chain can request custom **Whitelabel Documentation**, created and written by us, to empower their developers, educate their ecosystem, and support their end-users. We're flexible with how we can provide this documentation. Some teams might want to closely integrate our app-rollup documentation into their own existing docs, while others might want an entirely separate set of docs for their app-rollup. We offer a set of markdown docs as well as an out-of-the-box frontend, and are happy to work with teams to ensure that their docs suit the needs of their ecosystem's developers and community at-large.