UNPKG

@malda-protocol/protocol-config

Version:

Centralized contract addresses, constants, and token configurations for Malda Protocol

374 lines (286 loc) 11.2 kB
# @malda-protocol/protocol-config [![npm version](https://badge.fury.io/js/@malda-protocol%2Fprotocol-config.svg)](https://www.npmjs.com/package/@malda-protocol/protocol-config) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) Centralized contract addresses, constants, and token configurations for Malda Protocol across different environments and blockchain networks. ## Features - 🔒 **Type-safe**: Full TypeScript support with strict typing - 🌐 **Multi-chain**: Support for Mainnet, Arbitrum, Optimism, Base, and Linea - 🏗️ **Multi-environment**: Separate production and testnet configurations -**Runtime validation**: Zod schemas for configuration validation - 🔒 **Type-safe ABIs**: Full TypeScript inference for viem/wagmi contract interactions - 🎯 **Tree-shakeable**: Import only what you need - 📦 **Zero dependencies**: Minimal runtime dependencies (viem + zod) ## Installation ```bash npm install @malda-protocol/protocol-config # or yarn add @malda-protocol/protocol-config # or pnpm add @malda-protocol/protocol-config ``` ## Quick Start ```typescript import { PRODUCTION_CONFIG, PRODUCTION_TOKENS } from '@malda-protocol/protocol-config/production' // Get the production configuration console.log(PRODUCTION_CONFIG.hostChainId) // 59144 (Linea) console.log(PRODUCTION_CONFIG.operator) // "0x05bD298c0C3F34B541B42F867BAF6707911BE437" // Get production tokens console.log(PRODUCTION_TOKENS) // Array of all production tokens ``` ## Usage Examples ### Environment-Specific Imports ```typescript // Production configuration import * as production from '@malda-protocol/protocol-config/production' console.log(production.PRODUCTION_CONFIG) console.log(production.PRODUCTION_TOKENS) // Testnet configuration import * as testnet from '@malda-protocol/protocol-config/testnet' console.log(testnet.TESTNET_CONFIG) console.log(testnet.TESTNET_TOKENS) ``` ### Individual Token Access ```typescript import { production, testnet } from '@malda-protocol/protocol-config' // Production tokens const prodUSDC = production.USDC const prodWETH = production.WETH // Testnet tokens const testUSDC = testnet.USDC const testWETH = testnet.WETH ``` ### Chain-Specific Operations ```typescript import { getMarketsForChain, isMarketSupportedOnChain, TOKENS } from '@malda-protocol/protocol-config' import { mainnet, base, linea } from '@wagmi/core/chains' // Get markets available on Base const baseMarkets = getMarketsForChain(TOKENS, base.id) // Check if USDC is supported on Linea const usdcToken = TOKENS.find((t) => t.symbol === 'USDC') const isSupported = isMarketSupportedOnChain(usdcToken!, linea.id) ``` ### Using with Wagmi Chains ```typescript import { mainnet, arbitrum, optimism, base, linea } from '@wagmi/core/chains' import { getMarketsForChainObject, isMarketSupportedOnChainObject, getSupportedChainsForMarket, getNativeCurrencySymbol, getProductionChains, } from '@malda-protocol/protocol-config' import { PRODUCTION_CONFIG, PRODUCTION_TOKENS } from '@malda-protocol/protocol-config/production' // Get markets available on Base chain const baseMarkets = getMarketsForChainObject(PRODUCTION_TOKENS, base) console.log(`${baseMarkets.length} markets available on ${base.name}`) // Check if a specific token is supported on a wagmi chain const usdcToken = PRODUCTION_TOKENS.find((t) => t.symbol === 'USDC') const isUsdcOnArbitrum = isMarketSupportedOnChainObject(usdcToken!, arbitrum) // Get all chains that support a specific token const supportedChains = getSupportedChainsForMarket( usdcToken, [mainnet, arbitrum, optimism, base, linea], PRODUCTION_CONFIG ) // Access wagmi chain properties supportedChains.forEach((chain) => { console.log(`${chain.name}: ${getNativeCurrencySymbol(chain)}`) console.log(`Block Explorer: ${chain.blockExplorers?.default?.url}`) console.log(`RPC: ${chain.rpcUrls.default?.http[0]}`) }) // Filter production chains only const allChains = [mainnet, arbitrum, optimism, base, linea] const productionChains = getProductionChains(allChains) ``` ### Using ABIs with Viem/Wagmi ```typescript import { createPublicClient, http } from 'viem' import { mainnet } from 'viem/chains' import { useReadContract } from 'wagmi' import { ERC20_ABI, OPERATOR_ABI, MTOKEN_ABI, GAS_HELPER_ABI, JUMP_RATE_MODEL_ABI, } from '@malda-protocol/protocol-config/abis' import { PRODUCTION_CONFIG } from '@malda-protocol/protocol-config/production' // With viem - full type safety! const client = createPublicClient({ chain: mainnet, transport: http(), }) const balance = await client.readContract({ address: '0x...', // USDC address abi: ERC20_ABI, functionName: 'balanceOf', // ✅ Autocompleted and type-safe args: ['0x...'], // ✅ Args are type-checked }) // With wagmi hooks - also type-safe! function MyComponent() { const { data: liquidity } = useReadContract({ address: PRODUCTION_CONFIG.operator, abi: OPERATOR_ABI, functionName: 'getAccountLiquidity', // ✅ Type-safe args: ['0x...'], // ✅ Type-checked }) return <div>Liquidity: {liquidity?.toString()}</div> } // Dynamic ABI loading (for code splitting) import { getABI } from '@malda-protocol/protocol-config/abis' const erc20Abi = await getABI('ERC20') // Using jump rate models (per-mToken interest rate models) const usdcAsset = PRODUCTION_CONFIG.assets.find(asset => asset.symbol === 'USDC')! const borrowRate = await client.readContract({ address: usdcAsset.jumpRateModel, abi: JUMP_RATE_MODEL_ABI, functionName: 'getBorrowRate', // ✅ Type-safe args: [cash, borrows, reserves], // ✅ Type-checked }) ``` ### Runtime Validation ```typescript import { schemas, ProtocolConfigSchema } from '@malda-protocol/protocol-config' // Validate a configuration object const config = { /* ... */ } const result = ProtocolConfigSchema.safeParse(config) if (result.success) { console.log('Configuration is valid!') } else { console.error('Validation errors:', result.error.issues) } ``` ## API Reference ### Core Types ```typescript interface ProtocolConfig { hostChainId: number operator: Address priceOracle: Address blocksPerYear: number gasHelper: Address // ... more fields assets: ProtocolAsset[] supportedChainIds: number[] } interface ProtocolAsset { symbol: AssetSymbol name: string decimals: number addresses: { [chainId: number]: Address } // Underlying token addresses mToken: Address // mToken address jumpRateModel: Address // Interest rate model for this mToken nonGlobalAsset?: boolean supportedChainIds?: number[] } interface Token { name: string symbol: AssetSymbol decimals: number address: Address // mToken address underlyingAddresses: { [chainId: number]: Address } supportedChainIds?: number[] } ``` ### Constants - `PRODUCTION_CHAINS`, `TESTNET_CHAINS`, `ALL_CHAINS`: Wagmi chain objects for supported chains - `ASSET_SYMBOLS`: All supported asset symbols ### Environment-Specific Constants Use explicit imports for configuration and tokens: ```typescript // Production import { PRODUCTION_CONFIG, PRODUCTION_TOKENS } from '@malda-protocol/protocol-config/production' // Testnet import { TESTNET_CONFIG, TESTNET_TOKENS } from '@malda-protocol/protocol-config/testnet' ``` ### ABIs All ABIs are shared across environments and provide full TypeScript support: - `ERC20_ABI`: Standard ERC20 token interface - `OPERATOR_ABI`: Malda protocol operator contract - `MTOKEN_ABI`: Malda mToken contract - `MTOKEN_GATEWAY_ABI`: Malda mToken gateway contract - `GAS_HELPER_ABI`: Malda gas helper contract - `MIGRATOR_ABI`: Malda migrator contract - `PRICE_ORACLE_ABI`: Malda price oracle contract - `REFERRAL_SIGNING_ABI`: Malda referral signing contract - `USDT_MAINNET_ABI`: USDT mainnet specific ABI - `JUMP_RATE_MODEL_ABI`: Malda jump rate model contract (per-mToken) - `getABI(name)`: Dynamic ABI loader for code splitting - `ABIS`: Collection of all available ABIs with lazy loading ### Utility Functions #### Chain Operations (Primary API - supports wagmi Chain objects) - `isMarketSupportedOnChainObject(token, chain)`: Check if a token is supported on a wagmi chain - `getMarketsForChainObject(tokens, chain)`: Get all tokens available on a wagmi chain - `getSupportedChainsForMarket(token, allChains, config)`: Get supported wagmi chains for a token - `getUnderlyingAddressForChain(token, chain)`: Get underlying token address for a wagmi chain - `findChainById(chainId, chains)`: Find a wagmi chain object by its ID - `createTokensFromConfig(config)`: Transform protocol assets into simplified token format #### Wagmi Chain Utilities - `getNativeCurrencySymbol(chain)`: Get the native currency symbol (e.g., 'ETH') - `getRpcUrl(chain)`: Get the first RPC URL for a chain - `getBlockExplorerUrl(chain)`: Get the block explorer URL for a chain - `isTestnetChain(chain)`: Check if a wagmi chain is a testnet - `getProductionChains()`: Get predefined production (mainnet) chains - `getTestnetChains()`: Get predefined testnet chains #### Legacy Chain ID Operations - `isMarketSupportedOnChain(token, chainId)`: Check if a token is supported on a chain ID - `getMarketsForChain(tokens, chainId)`: Get all tokens available on a chain ID - `getUnderlyingAddress(token, chainId)`: Get underlying token address by chain ID ## Supported Assets | Symbol | Name | Decimals | Networks | | ------ | ------------------------- | -------- | ---------- | | USDC | USD Coin | 6 | All | | WETH | Wrapped Ether | 18 | All | | USDT | USD Tether | 6 | All | | WBTC | Wrapped BTC | 8 | All | | wstETH | Wrapped liquid staked ETH | 18 | All | | ezETH | Renzo Restaked ETH | 18 | Linea only | | weETH | Wrapped eETH | 18 | All | | wrsETH | Wrapped rsETH | 18 | All | ## Supported Networks ### Production - **Ethereum Mainnet** (1) - **Arbitrum One** (42161) - **Optimism** (10) - **Base** (8453) - **Linea** (59144) - Host Chain ### Testnet - **Sepolia** (11155111) - **Linea Sepolia** (59141) - Host Chain - **Optimism Sepolia** (11155420) ## Development ```bash # Install dependencies pnpm install # Build the package pnpm run build # Type check pnpm run type-check # Development mode (watch) pnpm run dev # Publishing check pnpm run publish:check ``` ## Contributing 1. All address and constant changes must be submitted via Pull Request 2. Changes require mandatory review (see CODEOWNERS) 3. Update version using `npm version patch|minor|major` 4. Follow semantic versioning ## Version Control This package uses semantic versioning. When making changes: - **Patch** (1.0.x): Bug fixes, address updates - **Minor** (1.x.0): New features, new assets, new chains - **Major** (x.0.0): Breaking changes to the API ### Releasing ```bash # Release a patch version pnpm run release:patch # Release a minor version pnpm run release:minor # Release a major version pnpm run release:major ``` ## License MIT © Malda Protocol