Using the CCIP JavaScript SDK

The CCIP JavaScript SDK is a tool that helps you to simplify management of cross-chain token transfers, and to integrate CCIP with the frontend of your own app.

The CCIP JavaScript SDK includes two packages:

  • ccip-js: A TypeScript library that provides a client for managing cross-chain token transfers that use CCIP routers. This package allows you to manage the steps you need to prepare before sending a CCIP message, as well as checking the transfer status afterward.
  • ccip-react-components: A set of prebuilt ready-to-use UI components built on top of ccip-js. This package includes the following features:
    • Customize injected wallet providers (MetaMask and Coinbase Wallet)
    • Specify preselected chains and tokens that will display as defaults when the component loads
    • Customize the UI theme
    • Configure allowlists and deny lists for which chains can be used, and which chains can be used as a sources or destinations for cross-chain transfers

Using both packages together, you can add a fully featured CCIP bridge to your app that can be styled to match your app design.

You can also use the ccip-js package on its own ā€” for example, to build a backend application. The features of the CCIP-JS package include:

  • Token approvals: Approve tokens for cross-chain transfers.
  • Allowance checks: Retrieve the allowance for token transfers.
  • Rate limits: Get rate refill limits for lanes.
  • Fee calculation: Calculate the fee required for transfers.
  • Token transfers: Transfer tokens across chains.
  • Transfer status: Retrieve the status of a transfer by transaction hash.

Install and run the SDK

  1. Install pnpm.

  2. Clone the ccip-javascript-sdk repo and navigate to the root directory of the ccip-javascript-sdk project:

    git clone https://github.com/smartcontractkit/ccip-javascript-sdk.git && cd ccip-javascript-sdk
    
  3. From the project root, run one of the following commands to install the SDK:

    pnpm install
    pnpm build
    pnpm dev-example
    
    • pnpm dev-example runs an example NextJS app locally. Navigate to http://localhost:3000 in your browser.

Run an example app

The example Next.js app included with the CCIP JavaScript SDK demonstrates the SDK's functionalities within an interactive web application, allowing you to see its features in action.

To get started:

  1. Launch the app by using the following commands:

    pnpm build
    pnpm dev-example
    
  2. In your browser, navigate to http://localhost:3000/ to see the interactive app:

    CCIP JavaScript SDK example app

Review a basic UI example

This basic UI example shows a basic token list configuration with CCIP-BnM and CCIP-LnM test tokens, and it lists the testnets you want to use with each one. This example also includes a basic frontend configuration.

Review the reference documentation:

Review the basic UI example below:

import 'ccip-react-components/dist/style.css';
import { CCIPWidget, Config, Token } from 'ccip-react-components';
import { sepolia, optimismSepolia } from 'viem/chains';

const tokensList: Token[] = [
  {
    symbol: 'CCIP-BnM',
    address: {
        [arbitrumSepolia.id]:'0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D',
        [avalancheFuji.id]: '0xD21341536c5cF5EB1bcb58f6723cE26e8D8E90e4',
        [baseSepolia.id]: '0x88A2d74F47a237a62e7A51cdDa67270CE381555e',
        [bscTestnet.id]: '0xbFA2ACd33ED6EEc0ed3Cc06bF1ac38d22b36B9e9',
        [optimismSepolia.id]: '0x8aF4204e30565DF93352fE8E1De78925F6664dA7',
        [polygonAmoy.id]: '0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4',
        [sepolia.id]: '0xFd57b4ddBf88a4e07fF4e34C487b99af2Fe82a05'
    },
    logoURL: 'https://smartcontract.imgix.net/tokens/ccip-bnm.webp?auto=compress%2Cformat',
    tags: ['chainlink', 'default']
  },
  {
    symbol: 'CCIP-LnM',
    address: {
      [optimismSepolia.id]: '0x044a6B4b561af69D2319A2f4be5Ec327a6975D0a',
      [sepolia.id]: '0x466D489b6d36E7E3b824ef491C225F5830E81cC1'
    },
    logoURL: 'https://smartcontract.imgix.net/tokens/ccip-lnm.webp?auto=compress%2Cformat',
    tags: ['chainlink', 'default']
  }
];

const config: Config = {
    theme: {
        pallette: {
            background: '#FFFFFF',
            border: '#B3B7C0',
            text: '#000000',
        }
        shape: {
            radius: 6
        },
    }
};

<CCIPWidget config={config} tokensList={tokensList} />;

Theme configuration

You can customize the component's theme to be in line with your app design. These are all the options available for theme configuration:

import { Config } from 'ccip-react-components';
const config: Config = { theme:
    {
    /** Define the app colors in HEX format */
    palette?: {
      /** Titles color and primary button background, default #000000 */
      primary?: string;
      /** Background color, default '#FFFFFF' */
      background?: string;
      /** Border color, default '#B3B7C0' */
      border?: string;
      /** Text color, default '#000000' */
      text?: string;
      /** Secondary text, inactive and placeholders color, default '#6D7480' */
      muted?: string;
      /** Input fields background color, default '#FFFFFF' */
      input?: string;
      /** Popovers, dropdowns and select fields background color, default '#F5F7FA' */
      popover?: string;
      /** Selected field from a dropdown background color, default '#D7DBE0' */
      selected?: string;
      /** Warning text color, default '#F7B955' */
      warning?: string;
      /** Warning text background color, default '#FFF5E0' */
      warningBackground?: string;
    };
    shape?: {
      /** Border radius size in px default 6 */
      radius?: number;
    };
  };}

Review a CCIP-JS example

This example uses the ccip-js package and covers the following steps:

  • Initialize CCIP-JS Client for mainnet
  • Approve tokens for transfer
  • Get fee for the transfer
  • Send the transfer through CCIP using one of the following options for fee payment:
    • Using the native token fee
    • Using the provided supported token for fee payment

Review the reference documentation for ccip-js.

Review the code

import * as CCIP from "@chainlink/ccip-js"
import { createWalletClient, custom } from "viem"
import { mainnet } from "viem/chains"

// Initialize CCIP-JS Client for mainnet
const ccipClient = CCIP.createClient()
const publicClient = createPublicClient({
  chain: mainnet,
  transport: http(),
})
const walletClient = createWalletClient({
  chain: mainnet,
  transport: custom(window.ethereum!),
})

// Approve Router to transfer tokens on user's behalf
const { txHash, txReceipt } = await ccipClient.approveRouter({
  client: walletClient,
  routerAddress: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
  tokenAddress: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
  amount: 1000000000000000000n,
  waitForReceipt: true,
})

console.log(`Transfer approved. Transaction hash: ${txHash}. Transaction receipt: ${txReceipt}`)

// Get fee for the transfer
const fee = await ccipClient.getFee({
  client: publicClient,
  routerAddress: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
  tokenAddress: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
  amount: 1000000000000000000n,
  destinationAccount: "0x1234567890abcdef1234567890abcdef12345678",
  destinationChainSelector: "1234",
})

console.log(`Fee: ${fee.toLocaleString()}`)

// Variant 1: Transfer via CCIP using native token fee
const { txHash, messageId } = await client.transferTokens({
  client: walletClient,
  routerAddress: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
  tokenAddress: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
  amount: 1000000000000000000n,
  destinationAccount: "0x1234567890abcdef1234567890abcdef12345678",
  destinationChainSelector: "1234",
})

console.log(`Transfer success. Transaction hash: ${txHash}. Message ID: ${messageId}`)

// Variant 2: Transfer via CCIP using the provided supported token for fee payment
const { txHash, messageId } = await client.transferTokens({
  client: walletClient,
  routerAddress: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
  tokenAddress: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
  amount: 1000000000000000000n,
  destinationAccount: "0x1234567890abcdef1234567890abcdef12345678",
  destinationChainSelector: "1234",
  feeTokenAddress: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
})

Build packages

Optionally, if you need to modify the packages and use your modified version, follow these instructions to build the packages:

You can use pnpm build to build both packages together. If you're building each package individually, make sure to build the build-ccip-js package before you build the ccip-react-components package. The React components depend on the JS package.

  1. Build the build-ccip-js package:
    pnpm i -w
    pnpm build-ccip-js
    
  2. Build the ccip-react-components package:
    pnpm build-components
    
  3. Update the ccip-react-components package to use the local ccip-js version by modifying the packages/ccip-react-components/package.json file. Replace the @chainlink/ccip-js dependency with the workspace reference:
    "@chainlink/ccip-js": "workspace:*"
    
  4. Update the examples/nextjs app to use both local ccip-js and ccip-react-components versions by modifying the examples/nextjs/package.json file. Replace the @chainlink/ccip-js and @chainlink/ccip-react-components dependencies with these relative paths:
    "@chainlink/ccip-js": "link:../../packages/ccip-js",
    "@chainlink/ccip-react-components": "link:../../packages/ccip-react-components",
    

Get the latest Chainlink content straight to your inbox.