-
Notifications
You must be signed in to change notification settings - Fork 406
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into ccip/1.5.1-remix
- Loading branch information
Showing
4 changed files
with
300 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,285 @@ | ||
--- | ||
section: ccip | ||
date: Last Modified | ||
title: "Using the CCIP JavaScript SDK" | ||
--- | ||
|
||
import { Aside, ClickToZoom } from "@components" | ||
import { Tabs } from "@components/Tabs" | ||
|
||
The [CCIP JavaScript SDK](https://github.com/smartcontractkit/ccip-javascript-sdk/tree/main) 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`](https://github.com/smartcontractkit/ccip-javascript-sdk/blob/main/packages/ccip-js/README.md): 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`](https://github.com/smartcontractkit/ccip-javascript-sdk/blob/main/packages/ccip-react-components/README.md): 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 | ||
|
||
<Aside type="caution" title="Security Warning: Handle Error Messages with Care"> | ||
**Important**: Error messages generated by this SDK are **not escaped**. If your application uses user inputs that may end up in error messages, it is your responsibility to **escape or sanitize these messages** before displaying them to users. | ||
|
||
Failure to escape or sanitize error messages could expose your application to **Cross-Site Scripting (XSS)** vulnerabilities, especially when user-generated content is included in error handling logic. | ||
|
||
</Aside> | ||
|
||
1. [Install `pnpm`](https://pnpm.io/installation). | ||
|
||
1. Clone the `ccip-javascript-sdk` repo and navigate to the root directory of the `ccip-javascript-sdk` project: | ||
|
||
```sh | ||
git clone https://github.com/smartcontractkit/ccip-javascript-sdk.git && cd ccip-javascript-sdk | ||
``` | ||
|
||
1. From the project root, run one of the following commands to install the SDK: | ||
|
||
{/* prettier-ignore */} | ||
<Tabs sharedStore="installOption" client:visible> | ||
<Fragment slot="tab.1">Install SDK and run example app</Fragment> | ||
<Fragment slot="tab.2">Install SDK only</Fragment> | ||
<Fragment slot="panel.1"> | ||
```sh | ||
pnpm install | ||
pnpm build | ||
pnpm dev-example | ||
``` | ||
</Fragment> | ||
<Fragment slot="panel.2"> | ||
```sh | ||
pnpm install | ||
``` | ||
</Fragment> | ||
</Tabs> | ||
- `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: | ||
|
||
```sh | ||
pnpm build | ||
pnpm dev-example | ||
``` | ||
|
||
1. In your browser, navigate to http://localhost:3000/ to see the interactive app: | ||
|
||
<ClickToZoom src="/images/ccip/ccip-sdk-example-app-ui.png" alt="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: | ||
|
||
- Listing tokens in [`tokensList`](https://github.com/smartcontractkit/ccip-javascript-sdk/tree/main/packages/ccip-react-components#tokens) | ||
- Configuring the frontend components in [`Config`](https://github.com/smartcontractkit/ccip-javascript-sdk/tree/main/packages/ccip-react-components#config) | ||
- Configuring a [theme for frontend styling](https://github.com/smartcontractkit/ccip-javascript-sdk/tree/main/packages/ccip-react-components#theme) | ||
|
||
Review the basic UI example below: | ||
|
||
```ts | ||
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: | ||
|
||
```ts | ||
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](https://github.com/smartcontractkit/ccip-javascript-sdk/tree/main/packages/ccip-js#api-reference) for `ccip-js`. | ||
|
||
### Review the code | ||
|
||
```ts | ||
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: | ||
```sh | ||
pnpm i -w | ||
pnpm build-ccip-js | ||
``` | ||
1. Build the `ccip-react-components` package: | ||
```sh | ||
pnpm build-components | ||
``` | ||
1. 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:*" | ||
``` | ||
1. 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", | ||
``` |