Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,22 @@ ccip-sdk-examples/

## Shared packages

### @ccip-examples/shared-config
### @chainlink/ccip-examples-shared-config

Network and token config; wagmi config and query client; constants (status labels, polling, explorer URLs). RPC URLs come from `getRpcUrl(networkId)` (env vars `RPC_<NETWORK_ID>` or public fallbacks).

- **Exports:** `NETWORKS`, `NETWORK_IDS`, `getNetwork`, `getEVMNetworks`, `getSolanaNetworks`, `getAptosNetworks`, `getAllNetworks`, `getChainIdForNetwork`, `getExplorerTxUrl`, `getExplorerAddressUrl`; `getTokenAddress`, `resolveFeeTokenAddress`, `TOKEN_ADDRESSES`, etc.; `ChainFamily`; `POLLING_CONFIG`, `getStatusDescription`, `getFaucetUrl`, `getDummyReceiver`, etc.
- **Subpaths:** `./wagmi`, `./queryClient`, `./networks`, `./tokens`.

### @ccip-examples/shared-utils
### @chainlink/ccip-examples-shared-utils

Browser-safe utilities: validation (`isValidAddress`, `isValidAmount`, `parseAmount`, `formatAmount`, `truncateAddress`), CCIP error parsing (`getCCIPErrorMessage`, `parseEVMError`, `parseSolanaError`), formatting (`formatLatency`, `formatElapsedTime`, `formatRelativeTime`), message building (`buildTokenTransferMessage`), clipboard (`copyToClipboard`, `COPIED_FEEDBACK_MS`), viem adapter (`toGenericPublicClient`). Node-only wallet/chain helpers live in `@ccip-examples/shared-utils/wallet`.
Browser-safe utilities: validation (`isValidAddress`, `isValidAmount`, `parseAmount`, `formatAmount`, `truncateAddress`), CCIP error parsing (`getCCIPErrorMessage`, `parseEVMError`, `parseSolanaError`), formatting (`formatLatency`, `formatElapsedTime`, `formatRelativeTime`), message building (`buildTokenTransferMessage`), clipboard (`copyToClipboard`, `COPIED_FEEDBACK_MS`), viem adapter (`toGenericPublicClient`). Node-only wallet/chain helpers live in `@chainlink/ccip-examples-shared-utils/wallet`.

- **Subpaths:** `./hooks` (e.g. `useMessageStatus`, `useCopyToClipboard`).

### @ccip-examples/shared-components
### @chainlink/ccip-examples-shared-components

React UI: primitives (Button, Input, Select, Alert), bridge (MessageProgress, TransferStatus, FeeTokenOptions, BalancesList), ErrorBoundary. All use design tokens from `@ccip-examples/shared-components/styles/tokens.css`. Import tokens once in app globals.
React UI: primitives (Button, Input, Select, Alert), bridge (MessageProgress, TransferStatus, FeeTokenOptions, BalancesList), ErrorBoundary. All use design tokens from `@chainlink/ccip-examples-shared-components/styles/tokens.css`. Import tokens once in app globals.

- **FeeTokenOptions:** Radio group for choosing fee token (native currency, LINK, or other tokens discovered from the router). Displays token name, symbol, balance, and a "Native" badge for native currency options.
- **BalancesList:** Displays multiple token balances with loading skeletons.
Expand Down
8 changes: 4 additions & 4 deletions docs/LEARNING_PATH.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Progressive examples for using `@chainlink/ccip-sdk` v1.0.0 (testnet only). Each
- **Runtime:** Node.js (no browser).
- **Purpose:** SDK basics without UI—chain setup, fee estimation, token discovery, pool inspection, cross-chain transfers.
- **Scripts:** `pnpm chains`, `pnpm fees`, `pnpm tokens`, `pnpm pools`, `pnpm transfer`, `pnpm status` (see example README).
- **Dependencies:** `@chainlink/ccip-sdk`, `@ccip-examples/shared-config`, `@ccip-examples/shared-utils` (chain factory, validation, message building).
- **Dependencies:** `@chainlink/ccip-sdk`, `@chainlink/ccip-examples-shared-config`, `@chainlink/ccip-examples-shared-utils` (chain factory, validation, message building).

### 02-evm-simple-bridge

Expand All @@ -19,7 +19,7 @@ Progressive examples for using `@chainlink/ccip-sdk` v1.0.0 (testnet only). Each
- **Fee token:** User selects a fee token via `FeeTokenOptions` (native currency, LINK, or other tokens discovered dynamically from the router via `getFeeTokens()`). Each option shows token name, symbol, balance, and a "Native" badge for native currency.
- **Balances:** `useWalletBalances` fetches native, LINK, and token balances in parallel; displayed via `BalancesList`.
- **Stack:** wagmi, viem, RainbowKit; chain from `getPublicClient` + `fromViemClient(toGenericPublicClient(...))`.
- **Shared:** `@ccip-examples/shared-config` (NETWORKS, wagmi config, tokens), `@ccip-examples/shared-utils` (validation, errors, formatting, hooks), `@ccip-examples/shared-components` (Button, Input, Select, Alert, FeeTokenOptions, BalancesList, TransferStatus, MessageProgress, ErrorBoundary), `@ccip-examples/shared-brand` (design tokens, logo).
- **Shared:** `@chainlink/ccip-examples-shared-config` (NETWORKS, wagmi config, tokens), `@chainlink/ccip-examples-shared-utils` (validation, errors, formatting, hooks), `@chainlink/ccip-examples-shared-components` (Button, Input, Select, Alert, FeeTokenOptions, BalancesList, TransferStatus, MessageProgress, ErrorBoundary), `@chainlink/ccip-examples-shared-brand` (design tokens, logo).
- **RPC:** Optional `.env` with `RPC_<NETWORK_ID>` (e.g. `RPC_ETHEREUM_TESTNET_SEPOLIA`) to override public RPC URLs.

### 03-multichain-bridge-dapp
Expand Down Expand Up @@ -54,8 +54,8 @@ CCIP routing uses **chain selectors** (64-bit identifiers), not wallet chain IDs
Call `getFee()` on the source chain before sending. Message shape follows SDK `MessageInput` (receiver, tokenAmounts, feeToken, extraArgs, etc.). Use `buildTokenTransferMessage` (shared-utils) for token transfers:

```typescript
import { buildTokenTransferMessage } from "@ccip-examples/shared-utils";
import { resolveFeeTokenAddress } from "@ccip-examples/shared-config";
import { buildTokenTransferMessage } from "@chainlink/ccip-examples-shared-utils";
import { resolveFeeTokenAddress } from "@chainlink/ccip-examples-shared-config";

// feeToken: undefined = native currency, address = ERC20 (e.g. LINK)
const feeTokenAddress = resolveFeeTokenAddress("link", sourceNetworkId);
Expand Down
24 changes: 12 additions & 12 deletions examples/01-getting-started/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ Message Found!

### Chain (base class)

All scripts use the abstract `Chain` base class. Concrete instances are created via the `createChain(networkId, rpcUrl)` factory from `@ccip-examples/shared-utils`.
All scripts use the abstract `Chain` base class. Concrete instances are created via the `createChain(networkId, rpcUrl)` factory from `@chainlink/ccip-examples-shared-utils`.

| Method | Description |
| ---------------------------------- | ------------------------------------- |
Expand All @@ -263,17 +263,17 @@ Used by `get-status.ts` for message lookups. No chain instance needed.

### Shared Utilities

| Function | Package | Description |
| ----------------------------- | ------------------------------ | ------------------------------------------------- |
| `createChain()` | `@ccip-examples/shared-utils` | Family-agnostic chain factory |
| `createWallet()` | `@ccip-examples/shared-utils` | Family-agnostic wallet factory (reads env vars) |
| `createSolanaWallet()` | `@ccip-examples/shared-utils` | Solana wallet from file path, hex, or base58 |
| `createAptosWallet()` | `@ccip-examples/shared-utils` | Aptos wallet from AIP-80 or hex private key |
| `createLogger()` | `@ccip-examples/shared-utils` | Logger with configurable verbosity |
| `buildTokenTransferMessage()` | `@ccip-examples/shared-utils` | Build a `MessageInput` for token transfers |
| `networkInfo()` | `@chainlink/ccip-sdk` | Get chain selector and metadata |
| `resolveFeeTokenAddress()` | `@ccip-examples/shared-config` | Resolve `"native"`/`"link"` to on-chain address |
| `getDummyReceiver()` | `@ccip-examples/shared-config` | Get a format-valid dummy address per chain family |
| Function | Package | Description |
| ----------------------------- | ---------------------------------------- | ------------------------------------------------- |
| `createChain()` | `@chainlink/ccip-examples-shared-utils` | Family-agnostic chain factory |
| `createWallet()` | `@chainlink/ccip-examples-shared-utils` | Family-agnostic wallet factory (reads env vars) |
| `createSolanaWallet()` | `@chainlink/ccip-examples-shared-utils` | Solana wallet from file path, hex, or base58 |
| `createAptosWallet()` | `@chainlink/ccip-examples-shared-utils` | Aptos wallet from AIP-80 or hex private key |
| `createLogger()` | `@chainlink/ccip-examples-shared-utils` | Logger with configurable verbosity |
| `buildTokenTransferMessage()` | `@chainlink/ccip-examples-shared-utils` | Build a `MessageInput` for token transfers |
| `networkInfo()` | `@chainlink/ccip-sdk` | Get chain selector and metadata |
| `resolveFeeTokenAddress()` | `@chainlink/ccip-examples-shared-config` | Resolve `"native"`/`"link"` to on-chain address |
| `getDummyReceiver()` | `@chainlink/ccip-examples-shared-config` | Get a format-valid dummy address per chain family |

## Solana-Specific Notes

Expand Down
12 changes: 8 additions & 4 deletions examples/01-getting-started/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"name": "@ccip-examples/01-getting-started",
"name": "@chainlink/ccip-examples-01-getting-started",
"private": true,
"version": "1.0.0",
"engines": {
"node": ">=22.0.0"
},
"description": "Getting started with CCIP SDK - Node.js scripts for basic operations",
"type": "module",
"scripts": {
Expand All @@ -18,9 +22,9 @@
"clean": "rm -rf dist"
},
"dependencies": {
"@ccip-examples/shared-config": "workspace:*",
"@ccip-examples/shared-utils": "workspace:*",
"@chainlink/ccip-sdk": "1.0.0",
"@chainlink/ccip-examples-shared-config": "workspace:*",
"@chainlink/ccip-examples-shared-utils": "workspace:*",
"@chainlink/ccip-sdk": "1.3.1",
"@coral-xyz/anchor": "^0.30.1",
"@solana/web3.js": "^1.98.0",
"bs58": "^6.0.0",
Expand Down
4 changes: 2 additions & 2 deletions examples/01-getting-started/src/estimate-fees.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ import {
resolveFeeTokenAddress,
type FeeTokenOption,
type NetworkConfig,
} from "@ccip-examples/shared-config";
} from "@chainlink/ccip-examples-shared-config";
import {
formatAmount,
parseAmount,
buildTokenTransferMessage,
createChain,
getErrorMessage,
} from "@ccip-examples/shared-utils";
} from "@chainlink/ccip-examples-shared-utils";

const DEFAULT_TOKEN = "CCIP-BnM";
const DEFAULT_AMOUNT = "1.0";
Expand Down
2 changes: 1 addition & 1 deletion examples/01-getting-started/src/get-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
CCIPMessageIdNotFoundError,
withRetry,
} from "@chainlink/ccip-sdk";
import { getStatusDescription, POLLING_CONFIG } from "@ccip-examples/shared-config";
import { getStatusDescription, POLLING_CONFIG } from "@chainlink/ccip-examples-shared-config";

async function main() {
const args = process.argv.slice(2);
Expand Down
4 changes: 2 additions & 2 deletions examples/01-getting-started/src/inspect-pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import "dotenv/config";
import type { Chain, RateLimiterState, TokenInfo } from "@chainlink/ccip-sdk";
import { networkInfo, CCIPError, CCIPTokenPoolChainConfigNotFoundError } from "@chainlink/ccip-sdk";
import { NETWORKS, NETWORK_IDS, getTokenAddress } from "@ccip-examples/shared-config";
import { formatAmount, createChain } from "@ccip-examples/shared-utils";
import { NETWORKS, NETWORK_IDS, getTokenAddress } from "@chainlink/ccip-examples-shared-config";
import { formatAmount, createChain } from "@chainlink/ccip-examples-shared-utils";

/**
* Format a rate limiter state for display.
Expand Down
2 changes: 1 addition & 1 deletion examples/01-getting-started/src/list-chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
type ChainFamily,
getAllNetworks,
CHAIN_FAMILY_LABELS,
} from "@ccip-examples/shared-config";
} from "@chainlink/ccip-examples-shared-config";

function main() {
console.log("=".repeat(60));
Expand Down
4 changes: 2 additions & 2 deletions examples/01-getting-started/src/supported-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
import "dotenv/config";
import { Command } from "commander";
import { networkInfo, CCIPError, CCIPTokenPoolChainConfigNotFoundError } from "@chainlink/ccip-sdk";
import { NETWORKS, NETWORK_IDS, CHAIN_FAMILY_LABELS } from "@ccip-examples/shared-config";
import { formatAmount, createChain } from "@ccip-examples/shared-utils";
import { NETWORKS, NETWORK_IDS, CHAIN_FAMILY_LABELS } from "@chainlink/ccip-examples-shared-config";
import { formatAmount, createChain } from "@chainlink/ccip-examples-shared-utils";

function validateChainKey(key: string): string {
if (!NETWORK_IDS.includes(key)) {
Expand Down
6 changes: 3 additions & 3 deletions examples/01-getting-started/src/transfer-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ import {
getDummyReceiver,
resolveFeeTokenAddress,
type FeeTokenOption,
} from "@ccip-examples/shared-config";
} from "@chainlink/ccip-examples-shared-config";
import {
formatAmount,
parseAmount,
buildTokenTransferMessage,
createChain,
createLogger,
} from "@ccip-examples/shared-utils";
import { createWallet } from "@ccip-examples/shared-utils/wallet";
} from "@chainlink/ccip-examples-shared-utils";
import { createWallet } from "@chainlink/ccip-examples-shared-utils/wallet";

const DEFAULT_TOKEN = "CCIP-BnM";
const DEFAULT_AMOUNT = "0.001";
Expand Down
6 changes: 3 additions & 3 deletions examples/02-evm-simple-bridge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ const walletClient = useWalletClient();
// 2. viem → CCIP SDK (adapters from SDK + shared-utils)
import { fromViemClient, viemWallet } from "@chainlink/ccip-sdk/viem";
import { CCIPAPIClient, networkInfo } from "@chainlink/ccip-sdk";
import { toGenericPublicClient } from "@ccip-examples/shared-utils";
import { toGenericPublicClient } from "@chainlink/ccip-examples-shared-utils";

// Chain instance for on-chain operations (fee, send)
const chain = await fromViemClient(toGenericPublicClient(publicClient));
Expand Down Expand Up @@ -298,7 +298,7 @@ src/
└── main.tsx # Entry point
```

**From shared packages** (via `@ccip-examples/*`):
**From shared packages** (via `@chainlink/ccip-examples-*`):

| Import | Package | Purpose |
| ------------------------------------------------------- | --------------------- | ------------------------- |
Expand Down Expand Up @@ -333,7 +333,7 @@ import {
buildTokenTransferMessage,
toGenericPublicClient,
categorizeError,
} from "@ccip-examples/shared-utils";
} from "@chainlink/ccip-examples-shared-utils";

// Create SDK chain from wagmi's public client
const publicClient = getPublicClient(wagmiConfig, { chainId });
Expand Down
16 changes: 10 additions & 6 deletions examples/02-evm-simple-bridge/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"name": "@ccip-examples/02-evm-simple-bridge",
"name": "@chainlink/ccip-examples-02-evm-simple-bridge",
"private": true,
"version": "1.0.0",
"engines": {
"node": ">=22.0.0"
},
"description": "Simple EVM-to-EVM bridge using wagmi, viem, and RainbowKit",
"type": "module",
"scripts": {
Expand All @@ -13,11 +17,11 @@
"clean": "rm -rf dist"
},
"dependencies": {
"@chainlink/ccip-sdk": "1.0.0",
"@ccip-examples/shared-brand": "workspace:*",
"@ccip-examples/shared-config": "workspace:*",
"@ccip-examples/shared-components": "workspace:*",
"@ccip-examples/shared-utils": "workspace:*",
"@chainlink/ccip-sdk": "1.3.1",
"@chainlink/ccip-examples-shared-brand": "workspace:*",
"@chainlink/ccip-examples-shared-config": "workspace:*",
"@chainlink/ccip-examples-shared-components": "workspace:*",
"@chainlink/ccip-examples-shared-utils": "workspace:*",
"@rainbow-me/rainbowkit": "^2.2.10",
"@tanstack/react-query": "^5.62.0",
"react": "^18.3.1",
Expand Down
14 changes: 7 additions & 7 deletions examples/02-evm-simple-bridge/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ import { WagmiProvider } from "wagmi";
import { RainbowKitProvider, darkTheme } from "@rainbow-me/rainbowkit";
import { useAccount, useSwitchChain } from "wagmi";

import { BRAND_COLORS } from "@ccip-examples/shared-brand";
import { wagmiConfig } from "@ccip-examples/shared-config/wagmi";
import { createDefaultQueryClient } from "@ccip-examples/shared-config/queryClient";
import type { FeeTokenOptionItem } from "@ccip-examples/shared-config";
import { BRAND_COLORS } from "@chainlink/ccip-examples-shared-brand";
import { wagmiConfig } from "@chainlink/ccip-examples-shared-config/wagmi";
import { createDefaultQueryClient } from "@chainlink/ccip-examples-shared-config/queryClient";
import type { FeeTokenOptionItem } from "@chainlink/ccip-examples-shared-config";
import {
ErrorBoundary,
MessageProgress,
TransferStatus,
Header,
} from "@ccip-examples/shared-components";
} from "@chainlink/ccip-examples-shared-components";
import { Footer } from "./components/layout";
import { WalletConnect, BridgeForm } from "./components/bridge";
import { useTransfer } from "./hooks";
import "@ccip-examples/shared-components/styles/globals.css";
import "@chainlink/ccip-examples-shared-components/styles/globals.css";
import "@rainbow-me/rainbowkit/styles.css";
import styles from "@ccip-examples/shared-components/layout/AppLayout.module.css";
import styles from "@chainlink/ccip-examples-shared-components/layout/AppLayout.module.css";

const queryClient = createDefaultQueryClient();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@

import { useState, useEffect, useCallback, useMemo } from "react";
import { networkInfo, ChainFamily } from "@chainlink/ccip-sdk";
import { NETWORKS, getTokenAddress, type FeeTokenOptionItem } from "@ccip-examples/shared-config";
import {
NETWORKS,
getTokenAddress,
type FeeTokenOptionItem,
} from "@chainlink/ccip-examples-shared-config";
import {
isValidEVMAddress,
isValidAmount,
formatAmountFull,
copyToClipboard,
COPIED_FEEDBACK_MS,
} from "@ccip-examples/shared-utils";
} from "@chainlink/ccip-examples-shared-utils";
import {
Select,
Input,
Expand All @@ -26,11 +30,11 @@ import {
CopyIcon,
CheckIcon,
type BalanceItem,
} from "@ccip-examples/shared-components";
import { useWalletBalances, useFeeTokens } from "@ccip-examples/shared-utils/hooks";
} from "@chainlink/ccip-examples-shared-components";
import { useWalletBalances, useFeeTokens } from "@chainlink/ccip-examples-shared-utils/hooks";
import { useGetChain } from "../../hooks/useGetChain.js";
import { NETWORK_TO_CHAIN_ID } from "@ccip-examples/shared-config/wagmi";
import styles from "@ccip-examples/shared-components/bridge/BridgeForm.module.css";
import { NETWORK_TO_CHAIN_ID } from "@chainlink/ccip-examples-shared-config/wagmi";
import styles from "@chainlink/ccip-examples-shared-components/bridge/BridgeForm.module.css";

/** Fixed token symbol for this bridge example */
const TOKEN_SYMBOL = "CCIP-BnM";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/

import { ConnectButton } from "@rainbow-me/rainbowkit";
import styles from "@ccip-examples/shared-components/bridge/WalletConnect.module.css";
import styles from "@chainlink/ccip-examples-shared-components/bridge/WalletConnect.module.css";

/**
* Wallet connection with RainbowKit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Bridge components (WalletConnect, BridgeForm). MessageProgress and TransferStatus from @ccip-examples/shared-components.
* Bridge components (WalletConnect, BridgeForm). MessageProgress and TransferStatus from @chainlink/ccip-examples-shared-components.
*/
export { WalletConnect } from "./WalletConnect";
export { BridgeForm } from "./BridgeForm";
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Uses centralized URLs from shared-config to avoid duplication.
*/

import { EXTERNAL_URLS } from "@ccip-examples/shared-config";
import { EXTERNAL_URLS } from "@chainlink/ccip-examples-shared-config";
import styles from "./Footer.module.css";

export function Footer() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Layout components barrel export.
* Header is from @ccip-examples/shared-components.
* Header is from @chainlink/ccip-examples-shared-components.
*/

export { Footer } from "./Footer";
2 changes: 1 addition & 1 deletion examples/02-evm-simple-bridge/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ export {
CHAIN_ID_TO_NETWORK,
NETWORK_TO_CHAIN_ID,
getWagmiChain,
} from "@ccip-examples/shared-config/wagmi";
} from "@chainlink/ccip-examples-shared-config/wagmi";
Loading
Loading