@malda-protocol/protocol-config
v2.0.7
Published
Centralized contract addresses, constants, and token configurations for Malda Protocol
Maintainers
Readme
@malda-protocol/protocol-config
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
npm install @malda-protocol/protocol-config
# or
yarn add @malda-protocol/protocol-config
# or
pnpm add @malda-protocol/protocol-configQuick Start
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 tokensUsage Examples
Environment-Specific Imports
// 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
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.WETHChain-Specific Operations
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
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
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
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
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 chainsASSET_SYMBOLS: All supported asset symbols
Environment-Specific Constants
Use explicit imports for configuration and tokens:
// 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 interfaceOPERATOR_ABI: Malda protocol operator contractMTOKEN_ABI: Malda mToken contractMTOKEN_GATEWAY_ABI: Malda mToken gateway contractGAS_HELPER_ABI: Malda gas helper contractMIGRATOR_ABI: Malda migrator contractPRICE_ORACLE_ABI: Malda price oracle contractREFERRAL_SIGNING_ABI: Malda referral signing contractUSDT_MAINNET_ABI: USDT mainnet specific ABIJUMP_RATE_MODEL_ABI: Malda jump rate model contract (per-mToken)getABI(name): Dynamic ABI loader for code splittingABIS: 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 chaingetMarketsForChainObject(tokens, chain): Get all tokens available on a wagmi chaingetSupportedChainsForMarket(token, allChains, config): Get supported wagmi chains for a tokengetUnderlyingAddressForChain(token, chain): Get underlying token address for a wagmi chainfindChainById(chainId, chains): Find a wagmi chain object by its IDcreateTokensFromConfig(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 chaingetBlockExplorerUrl(chain): Get the block explorer URL for a chainisTestnetChain(chain): Check if a wagmi chain is a testnetgetProductionChains(): Get predefined production (mainnet) chainsgetTestnetChains(): Get predefined testnet chains
Legacy Chain ID Operations
isMarketSupportedOnChain(token, chainId): Check if a token is supported on a chain IDgetMarketsForChain(tokens, chainId): Get all tokens available on a chain IDgetUnderlyingAddress(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
# 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:checkContributing
- All address and constant changes must be submitted via Pull Request
- Changes require mandatory review (see CODEOWNERS)
- Update version using
npm version patch|minor|major - 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
# Release a patch version
pnpm run release:patch
# Release a minor version
pnpm run release:minor
# Release a major version
pnpm run release:majorLicense
MIT © Malda Protocol
