@malda-protocol/protocol-config
Version:
Centralized contract addresses, constants, and token configurations for Malda Protocol
374 lines (286 loc) • 11.2 kB
Markdown
# @malda-protocol/protocol-config
[](https://www.npmjs.com/package/@malda-protocol/protocol-config)
[](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