Skip to content
This repository was archived by the owner on Mar 17, 2026. It is now read-only.
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
14 changes: 7 additions & 7 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ jobs:
runs-on: ubuntu-latest
environment: publish
permissions:
contents: read
contents: read
steps:
- name: Checkout the repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
fetch-depth: 0

- name: Setup Node 18.x
- name: Setup Node 20.x
uses: actions/setup-node@v3
with:
node-version: 18.12
node-version: 20.19
always-auth: true

- name: Install PNPM
Expand Down Expand Up @@ -56,17 +56,17 @@ jobs:
if: github.ref_name != 'main'
runs-on: ubuntu-latest
permissions:
contents: read
contents: read
steps:
- name: Checkout the repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
fetch-depth: 0

- name: Setup Node 18.x
- name: Setup Node 20.x
uses: actions/setup-node@v3
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should pin to commit hashes.

with:
node-version: 18.12
node-version: 20.19
always-auth: true

- name: Install PNPM
Expand All @@ -90,4 +90,4 @@ jobs:
pnpm build-components
cd packages/ccip-react-components
pnpm publish --no-git-checks --access public --dry-run
shell: bash
shell: bash
11 changes: 9 additions & 2 deletions packages/ccip-js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ Retrieves the transaction receipt based on the transaction hash. Returns a promi
getTransactionReceipt(options: { client: Viem.Client; hash: Viem.Hash }): Promise<Viem.TransactionReceipt>
```

### Development
### Development (For developing this CCIP-JS package locally)

#### Build

Expand All @@ -600,14 +600,21 @@ pnpm i -w
pnpm build-ccip-js
```

Note that when the above `build-ccip-js` step is run, the contracts located in `./src/contracts` are compiled and ABIs and artifacts are emitted into the `../ccip-js/artifacts`
folder. From there, the relevant ABI arrays must be manually moved to `./src/abi` , and just the ABI array is pasted into the corresponding file in `./src/abi`. However the files in `./artifacts-compile` contain objects with both the abi and the bytecode and are used in the unit test files with Viem's test clients.

#### Running tests

1. cd into `packages/ccip-js` and then run `pnpm install` OR from the project root you can run `pnpm i -w`

2. open a new terminal window and run `foundryup` followed by `anvil` - requires that you've [installed Foundry Anvil](https://book.getfoundry.sh/anvil/).
<b?>Note:</b> that Anvil is only needed for the integrations tests inside `./test` which uses the [Chainlink Local](https://github.com/smartcontractkit/chainlink-local) simulator. Actual testnet and mainnet behavior may differ from time to time and passing these tests does not guarantee testnet or mainnet behavior.

3. Back in the first terminal, inside, `packages/ccip-js` run `pnpm t:int` or `pnpm t:uint`. Note some tests are flaky - this is under investigation. You can choose to run just the mocked test or the testnet integration tests using `pnpm jest <<name of test file>>`.
3. Back in the first terminal, inside, `packages/ccip-js` run `export PRIVATE_KEY=xxxxxx` to set your private key and then run `pnpm t:int` or `pnpm t:uint`.

Note some tests are flaky - this is under investigation. You can choose to run just the mocked test or the testnet integration tests using `pnpm jest <<name of test file>>`.

Note further that we have set a 180000ms (3 mins) timeout on the jest config. This can cause the testnet integration test to "hang" for the entire duration.

### Contributing

Expand Down
26 changes: 13 additions & 13 deletions packages/ccip-js/hardhat.config.cjs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
require("@nomicfoundation/hardhat-toolbox");
require("@nomicfoundation/hardhat-ethers");
require("@nomicfoundation/hardhat-viem");
require('@nomicfoundation/hardhat-toolbox')
require('@nomicfoundation/hardhat-ethers')
require('@nomicfoundation/hardhat-viem')

require("chai");
require("mocha");
require("ethers");
require('chai')
require('mocha')
require('ethers')
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.24",
solidity: '0.8.24',
solc: {
version: "0.8.24",
version: '0.8.24',
},
paths: {
sources: "src/contracts",
tests: "./test",
cache: "./cache",
artifacts: "./artifacts",
sources: 'src/contracts',
tests: './test',
cache: './cache',
artifacts: './artifacts',
},
};
}
13 changes: 7 additions & 6 deletions packages/ccip-js/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/** @type {import('ts-jest').JestConfigWithTsJest} **/
export default {
testEnvironment: 'node',
transform: {
'^.+.tsx?$': ['ts-jest', {}],
},
workerThreads: true,
};
testEnvironment: 'node',
transform: {
'^.+.tsx?$': ['ts-jest', {}],
},
workerThreads: true,
testTimeout: 180000,
}
2 changes: 1 addition & 1 deletion packages/ccip-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"lint": "eslint 'src/**/*.{ts,js}'",
"format": "prettier --write 'src/**/*.{ts,js,json,md}'",
"t:int": "jest --coverage -u --testMatch=\"**/integration-testnet.test.ts\" --detectOpenHandles",
"t:unit": "jest --coverage -u -t=\"Unit\"",
"t:unit": "jest --coverage -u --testMatch=\"**/unit.test.ts\" ",
"test:hh": "hardhat test"
},
"devDependencies": {
Expand Down
2 changes: 0 additions & 2 deletions packages/ccip-js/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import OnRampABI from './abi/OnRamp.json'
import OnRampABI_1_6 from './abi/OnRamp_1_6.json'
import IERC20ABI from './abi/IERC20Metadata.json'
import TokenPoolABI from './abi/TokenPool.json'
import PriceRegistryABI from './abi/PriceRegistry.json'
import FeeQuoterABI from './abi/FeeQuoter.json'
import TokenAdminRegistryABI from './abi/TokenAdminRegistry.json'
import { TRANSFER_STATUS_FROM_BLOCK_SHIFT, ExecutionStateChangedABI } from './config'
import { parseAbi } from 'viem'
Expand Down
4 changes: 2 additions & 2 deletions packages/ccip-js/src/contracts/FeeQuoter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet

/// @notice The FeeQuoter contract responsibility is to store the current gas price in USD for a given destination chain,
/// and the price of a token in USD allowing the owner or priceUpdater to update this value.
contract FeeQuoter is IFeeQuoter, OwnerIsCreator {
abstract contract FeeQuoter is IFeeQuoter, OwnerIsCreator {
using EnumerableSet for EnumerableSet.AddressSet;
using USDPriceWith18Decimals for uint224;

Expand Down Expand Up @@ -124,7 +124,7 @@ contract FeeQuoter is IFeeQuoter, OwnerIsCreator {
return (_getValidatedTokenPrice(feeToken), gasPrice.value);
}

/// @inheritdoc IFeeQuoter

/// @dev this function assumed that no more than 1e59 dollar, is sent as payment.
/// If more is sent, the multiplication of feeTokenAmount and feeTokenValue will overflow.
/// Since there isn't even close to 1e59 dollars in the world economy this is safe.
Expand Down
4 changes: 3 additions & 1 deletion packages/ccip-js/test/helpers/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Address, Hash, Hex, TransactionReceipt } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import dotenv from 'dotenv'

import bridgeJson from '../../artifacts-compile/BridgeToken.json'
import onRampJson from '../../artifacts-compile/EVM2EVMOnRamp.json'
import routerJson from '../../artifacts-compile/Router.json'
Expand All @@ -15,7 +16,8 @@ if (process.env.PRIVATE_KEY?.slice(0, 2) !== '0x') {
process.env.PRIVATE_KEY = `0x${process.env.PRIVATE_KEY}`
}

export const DEFAULT_ANVIL_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
export const DEFAULT_ANVIL_PRIVATE_KEY =
'0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' as Hex
export const account = privateKeyToAccount(DEFAULT_ANVIL_PRIVATE_KEY)

// bridge token contract
Expand Down
2 changes: 1 addition & 1 deletion packages/ccip-js/test/helpers/contracts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formatEther, getContract, type Address, type Hex } from 'viem'
import { getContract, type Address, type Hex } from 'viem'
import {
account,
bridgeTokenAbi,
Expand Down
12 changes: 8 additions & 4 deletions packages/ccip-js/test/integration-testnet.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { jest, expect, it, beforeAll, describe, afterAll } from '@jest/globals'
import { expect, it, afterAll, beforeAll, describe } from '@jest/globals'
import * as CCIP from '../src/api'
import * as Viem from 'viem'
import { sepolia, avalancheFuji } from 'viem/chains'
Expand All @@ -18,23 +18,23 @@ const LINK_TOKEN_FUJI = '0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846'
// 6m to match https://viem.sh/docs/actions/public/waitForTransactionReceipt.html#timeout-optional,
// which is called in approveRouter()
// TODO @zeuslawyer: https://prajjwaldimri.medium.com/why-is-my-jest-runner-not-closing-bc4f6632c959 - tests are passing but jest is not closing. Viem transport issue? why?
const TIMEOUT = 180 * 1000 // 3m
// currently timeout set to 180000ms in jest.config.js

if (!SEPOLIA_RPC_URL) {
throw new Error('SEPOLIA_RPC_URL must be set')
}
if (!AVALANCHE_FUJI_RPC_URL) {
throw new Error('AVALANCHE_FUJI_RPC_URL must be set')
}
const privateKey = process.env.PRIVATE_KEY as `0x${string}`

const privateKey = process.env.PRIVATE_KEY as Viem.Hex

if (privateKey === DEFAULT_ANVIL_PRIVATE_KEY) {
throw new Error(
"Developer's PRIVATE_KEY for Ethereum Sepolia and Avalanche Fuji must be set for integration testing on",
)
}

jest.setTimeout(TIMEOUT)
describe('Integration: Fuji -> Sepolia', () => {
let avalancheFujiClient: Viem.WalletClient
let sepoliaClient: Viem.WalletClient
Expand Down Expand Up @@ -290,4 +290,8 @@ describe('Integration: Fuji -> Sepolia', () => {
expect(ccipSend_txReceipt.to!.toLowerCase()).toEqual(AVALANCHE_FUJI_CCIP_ROUTER_ADDRESS.toLowerCase())
})
})

afterAll(async () => {
console.info('✅ | Testnet Integration tests passed. Waiting for timeout...')
})
})
2 changes: 0 additions & 2 deletions packages/ccip-js/test/unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { jest, expect, it, describe, afterEach } from '@jest/globals'
import * as CCIP from '../src/api'
import * as Viem from 'viem'
import * as viemActions from 'viem/actions'
import { sepolia } from 'viem/chains'
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
import { forkClient } from './helpers/clients'

const ccipClient = CCIP.createClient()
Expand Down
6 changes: 4 additions & 2 deletions packages/ccip-js/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
"lib": ["es2020", "esnext"],
"target": "ES2020",
"module": "esnext",
"moduleResolution": "node10",
"moduleResolution": "node",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
Expand All @@ -15,4 +17,4 @@
"sourceMap": true
},
"include": ["src"]
}
}