CCIP SDK
TypeScript SDK for sending, tracking, and executing cross-chain messages on CCIP.
Package
@chainlink/ccip-sdkVersion0.96.0
Node.jsv20+ (v23+ recommended)
LicenseMIT
Installation
- npm
- pnpm
- yarn
Bash
npm install @chainlink/ccip-sdk
Bash
pnpm add @chainlink/ccip-sdk
Bash
yarn add @chainlink/ccip-sdk
Quick Start
TypeScript
import { EVMChain } from '@chainlink/ccip-sdk'
// Connect to Ethereum Sepolia
const chain = await EVMChain.fromUrl('https://rpc.sepolia.org')
console.log('Connected to:', chain.network.name)
// Fetch CCIP requests from a transaction
const requests = await chain.getMessagesInTx('0x...')
for (const req of requests) {
console.log('Message ID:', req.message.messageId)
console.log('Destination:', req.lane.destChainSelector)
}
Prerequisites
You need RPC endpoints for the chains you want to interact with. Node.js v20+ is required (v23+ recommended for native fetch support).
- EVM
- Solana
- Aptos
- QuickNode - Multi-chain support with free tier
- Alchemy - Enterprise-grade with free tier
- Chainlist.org - Free public RPCs for EVM networks
- Infura - Reliable EVM endpoints with free tier
- Nodereal - Aptos and EVM support with free tier
Tip: For quick testing, Chainlist.org provides free public RPCs. For production, use Alchemy or Infura for better rate limits.
- QuickNode - Multi-chain support with free tier
- Alchemy - Enterprise-grade with free tier
- Helius - Popular Solana RPC with generous free tier
- Solana Official - Free but rate-limited official endpoints
Tip: For development, Helius offers a generous free tier. Official Solana endpoints are rate-limited but work for testing.
- QuickNode - Multi-chain support with free tier
- Aptos Labs - Official Aptos endpoints
- Nodereal - Aptos and EVM support with free tier
Tip: Official Aptos Labs endpoints work well for development. For production, consider QuickNode or Nodereal.
Chain Support
Supported chain families:
EVM
Solana
Aptos
Quick Reference
| Task | Method | Reference |
|---|---|---|
| Connect to chain | EVMChain.fromUrl(rpcUrl) | EVMChain |
| Track message | chain.getMessagesInTx(txHash) | getMessagesInTx |
| Get fee | chain.getFee({ router, destChainSelector, message }) | getFee |
| Send message | chain.sendMessage({ router, destChainSelector, message }) | sendMessage |
| Manual execution | calculateManualExecProof(request) | calculateManualExecProof |
| Decode message | decodeMessage(log) | decodeMessage |
Concepts
Chain Classes
| Class | Blockchain | Import |
|---|---|---|
| EVMChain | Ethereum, Arbitrum, Optimism, etc. | import { EVMChain } from '@chainlink/ccip-sdk' |
| SolanaChain | Solana | import { SolanaChain } from '@chainlink/ccip-sdk' |
| AptosChain | Aptos | import { AptosChain } from '@chainlink/ccip-sdk' |
| SuiChain | Sui | import { SuiChain } from '@chainlink/ccip-sdk' |
| TONChain | TON | import { TONChain } from '@chainlink/ccip-sdk' |
Message Lifecycle
- Sent - Message emitted on source chain (CCIPRequest)
- Committed - Merkle root committed on destination (CommitReport)
- Executed - Message executed on destination (ExecutionReceipt)
Chain Selectors vs Chain IDs
CCIP uses chain selectors (not chain IDs) to identify networks. Chain selectors are unique identifiers assigned by CCIP that remain consistent across the protocol.
TypeScript
import { networkInfo } from '@chainlink/ccip-sdk'
// Wrong: Using chain ID for CCIP operations
const destChain = 84532 // Base Sepolia chain ID - DON'T USE
// Correct: Using CCIP chain selector
const destSelector = networkInfo('ethereum-testnet-sepolia-base-1').chainSelector
// Returns: 10344971235874465080n
Always use chain selectors for:
destChainSelectorin messages- Lane configuration
- Fee estimation
Use networkInfo() to convert between chain IDs, names, and selectors.
Extra Arguments
Configure gas limits and execution parameters:
TypeScript
import { encodeExtraArgs } from '@chainlink/ccip-sdk'
const extraArgs = encodeExtraArgs({
gasLimit: 200000n,
allowOutOfOrderExecution: true,
})
Error Handling
The SDK throws typed errors:
TypeScript
import {
EVMChain,
CCIPMessageNotFoundInTxError,
CCIPBlockNotFoundError,
} from '@chainlink/ccip-sdk'
try {
const requests = await chain.getMessagesInTx(txHash)
} catch (error) {
if (error instanceof CCIPMessageNotFoundInTxError) {
console.log('No CCIP messages in transaction:', error.context.txHash)
} else if (error instanceof CCIPBlockNotFoundError) {
console.log('Block not found:', error.context.block)
} else {
throw error
}
}
See Error Handling for recovery patterns.
Next Steps
- EVMChain - EVM chain operations
- getMessagesForSender - Query by sender address
- calculateManualExecProof - Manual execution