Skip to content
Draft
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
46 changes: 46 additions & 0 deletions .agent/playbooks/RELEASE_PLAYBOOK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Release Playbook

Step-by-step guide for publishing beta and stable releases of `@chainlink/local`.

## Release and Publish Rules
- Publishing workflow: `.github/workflows/publish.yml`
- Triggers:
- automatic on tag push `v*`
- manual fallback via `workflow_dispatch`
- Before publishing any beta or stable release, `CHANGELOG.md` must be updated for that version using [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Version check:
- tag version must match `package.json` version
- Branch policy:
- beta tag (`vX.Y.Z-beta`) must come from `develop`
- stable tag (`vX.Y.Z`) must come from `main`

## Feature Development (beta track)
1. Branch from `develop` (for example `feat/<name>`, or `devrel-123/<name>`).
2. Open a draft PR targeting `develop`.
3. Commit incrementally using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
4. Keep docs/tests updated (`npm run generate-docs` when docs sources changed).
5. Mark PR ready, get review, merge into `develop`.

## Publish Beta Release
1. Ensure `package.json` version is beta-formatted (for example `0.3.1-beta`).
2. Update `CHANGELOG.md` for the new release using [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) + [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
3. Draft GitHub release with:
- tag: `v<version>-beta`
- target: `develop`
- pre-release: enabled
- release title: `v<version>-beta`
4. Publish the release (tag push triggers publish workflow automatically).
5. If needed, use manual `workflow_dispatch` fallback from `develop` with `release_type=beta`.

## Promote to Stable Release
1. Open PR from `develop` to `main`.
2. Update `package.json` version to stable (remove `-beta` suffix).
3. Update `CHANGELOG.md` for the stable release using [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) + [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4. Merge into `main` after review.
5. Draft GitHub release with:
- tag: `v<version>`
- target: `main`
- pre-release: disabled
- release title: `v<version>`
6. Publish release (tag push triggers stable publish automatically).
7. If needed, run manual fallback from `main` with `release_type=stable`.
6 changes: 6 additions & 0 deletions .claude/skills/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
name: release
description: Use when publishing a beta or stable release, creating release tags, or following the release workflow
---

Read `.agent/playbooks/RELEASE_PLAYBOOK.md` in the repository root and follow the instructions for the requested release type (beta or stable).
6 changes: 6 additions & 0 deletions .cursor/rules/general.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
description: General project rules for Chainlink Local
globs:
---

All project rules, conventions, and commands are in [AGENTS.md](../../AGENTS.md) at the repository root. Read it before starting any task.
63 changes: 43 additions & 20 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Use Node.js
uses: actions/setup-node@v4
Expand Down Expand Up @@ -76,11 +78,8 @@ jobs:
id: release-type
run: |
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" =~ ^refs/tags/v.* ]]; then
# Get the branch that was tagged (usually the default branch of the tag)
BRANCH_NAME="${{ github.ref_name }}"

# Check if tag contains 'beta' to determine release type
if [[ "${{ github.ref_name }}" == *"beta"* ]]; then
if [[ "${{ github.ref_name }}" == *"-beta"* ]]; then
echo "type=beta" >> $GITHUB_OUTPUT
echo "expected_branch=develop" >> $GITHUB_OUTPUT
else
Expand All @@ -99,32 +98,56 @@ jobs:

- name: Validate branch for release type
run: |
CURRENT_BRANCH="${{ github.ref_name }}"
EXPECTED_BRANCH="${{ steps.release-type.outputs.expected_branch }}"
RELEASE_TYPE="${{ steps.release-type.outputs.type }}"

echo "Current branch: $CURRENT_BRANCH"
echo "Expected branch for $RELEASE_TYPE release: $EXPECTED_BRANCH"

# For manual dispatch, we can't validate branch, so skip
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "⚠️ Manual dispatch detected - skipping branch validation"
echo "Please ensure you're running from the correct branch:"
echo "- Beta releases should be from 'develop' branch"
echo "- Stable releases should be from 'main' branch"

if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" =~ ^refs/tags/v.* ]]; then
TAG_NAME="${{ github.ref_name }}"
TAG_SHA="${{ github.sha }}"

echo "Tag: $TAG_NAME"
echo "Tag commit: $TAG_SHA"
echo "Expected branch for $RELEASE_TYPE release: $EXPECTED_BRANCH"

# Ensure expected branch ref exists locally.
if ! git fetch --no-tags --prune origin "${EXPECTED_BRANCH}"; then
echo "❌ Branch validation failed!"
echo "Could not fetch expected branch from origin: $EXPECTED_BRANCH"
exit 1
fi

if ! git show-ref --verify --quiet "refs/remotes/origin/${EXPECTED_BRANCH}"; then
echo "❌ Branch validation failed!"
echo "Could not fetch expected branch: $EXPECTED_BRANCH"
exit 1
fi

# Validate the tagged commit belongs to expected branch history.
if ! git merge-base --is-ancestor "$TAG_SHA" "origin/${EXPECTED_BRANCH}"; then
echo "❌ Branch validation failed!"
echo "Tag commit is not contained in branch: $EXPECTED_BRANCH"
echo "Please create the tag from the correct branch"
exit 1
fi

echo "✅ Tag ancestry validation passed"
exit 0
fi

# For tag pushes, validate branch

# workflow_dispatch: validate selected branch directly.
CURRENT_BRANCH="${{ github.ref_name }}"
echo "Selected workflow branch: $CURRENT_BRANCH"
echo "Expected branch for $RELEASE_TYPE release: $EXPECTED_BRANCH"

if [[ "$CURRENT_BRANCH" != "$EXPECTED_BRANCH" ]]; then
echo "❌ Branch validation failed!"
echo "Current branch: $CURRENT_BRANCH"
echo "Expected branch for $RELEASE_TYPE release: $EXPECTED_BRANCH"
echo "Please create the tag from the correct branch"
echo "For manual runs, choose the correct branch in 'Use workflow from'."
exit 1
fi
echo "✅ Branch validation passed"

echo "✅ Manual branch validation passed"

- name: Publish stable release
if: steps.release-type.outputs.type == 'stable'
Expand Down
10 changes: 10 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,13 @@
[submodule "lib/chainlink-ccip"]
path = lib/chainlink-ccip
url = https://github.com/smartcontractkit/chainlink-ccip
branch = develop
[submodule "lib/openzeppelin-contracts-4.8.3"]
path = lib/openzeppelin-contracts-4.8.3
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "lib/openzeppelin-contracts-5.3.0"]
path = lib/openzeppelin-contracts-5.3.0
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "lib/chainlink-ace"]
path = lib/chainlink-ace
url = https://github.com/smartcontractkit/chainlink-ace
124 changes: 124 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Chainlink Local - Agents Guide

Guide for AI coding agents working in `smartcontractkit/chainlink-local`.

## What this library does

Chainlink Local is a developer-focused testing package that simulates Chainlink services (especially CCIP) in local and forked environments.

- Local mode (`CCIPLocalSimulator`, `DataStreamsLocalSimulator`) lets developers test app logic quickly without waiting for live offchain systems.
- Fork mode (`CCIPLocalSimulatorFork`, `DataStreamsLocalSimulatorFork`) runs against forked networks so integrations behave closer to real testnet conditions.
- The intent is parity of user app behavior between local/fork testing and testnet deployment (minus environment-specific addresses/config).
- It is available for usage in Foundry, Hardhat 3, Hardhat 2 and Remix IDE environments.
- Official documentation is available at: https://docs.chain.link/chainlink-local

## Goal
- Make minimal, correct changes that preserve simulator behavior and test ergonomics.
- Prefer targeted edits and targeted tests over broad refactors.

## Context Budget First
Load files in this order and stop as soon as you have enough context:
1. `package.json` (scripts, versions, docs/release commands)
2. `foundry.toml` and `hardhat.config.ts` (tooling layout)
3. Only the relevant `src/**` files and matching tests in `test/**`
4. If docs task: `helper_doc/*.mjs` and `api_reference/**`
5. If release/publish task: `.github/workflows/publish.yml`

Avoid loading large/unnecessary trees unless explicitly required:
- `lib/**`, `out/**`, `cache/**`, `artifacts/**`, `node_modules/**`

## Directory layout
- `src/`: production contracts by service (`ccip`, `data-feeds`, `data-streams`)
- `src/test/`: helper/example contracts used by tests
- `test/smoke/`: local-mode tests
- `test/e2e/`: fork-mode tests
- `test/unit/`: unit-level tests
- `scripts/`: helpers for Hardhat users that write tests using JavaScript or TypeScript
- `helper_doc/`: docs generation scripts (you shouldn't touch these)
- `api_reference/`: generated docs output (read only; do not edit directly)

## Hard Rules
- Never edit `lib/**`. If user explicitly asks, use forge for dependency management.
- Never edit `node_modules/**`. If user explicitly asks, use npm for dependency management.
- Keep changes surgical; do not refactor unrelated code.
- Preserve test placement conventions:
- local mode -> `test/smoke/**`
- fork mode -> `test/e2e/**`
- Do not hand-edit generated docs in `api_reference/**`; regenerate via scripts.
- If a command fails after deleting generated docs, restore state before continuing.

## Common Commands
- Compile:
- `npm run forge-compile`
- `npm run hardhat-compile`
- Test:
- `npm run forge-test`
- `npm run hardhat-test`
- `forge test <path-to-test>`
- Docs:
- `npm run generate-docs` (deterministic; does not fetch Register data)
- `npm run update-register` (networked; updates `src/ccip/Register.sol`)

## Release and Publish
For the full release workflow (beta, stable, branch policy, CHANGELOG requirements), see [`.agent/playbooks/RELEASE_PLAYBOOK.md`](.agent/playbooks/RELEASE_PLAYBOOK.md).

## Dependency Policy
- Keep `@chainlink/contracts` and `@chainlink/contracts-ccip` as direct `dependencies`.
- Avoid introducing new tooling dependencies unless there is a clear maintenance win.
- If bumping Chainlink packages, do not move them to `devDependencies` or `peerDependencies`.

### Current core npm dependency versions
| Package | Version |
| --- | --- |
| `@chainlink/contracts-ccip` | `1.6.2` |
| `@chainlink/contracts` | `1.5.0` |

## Dependency Update Playbook
Use these commands unless a maintainer requests something different.

### npm / Hardhat dependencies
- Add runtime dependency:
- `npm install <package>@<version>`
- Add dev dependency:
- `npm install --save-dev <package>@<version>`
- Update existing dependency:
- `npm install <package>@<new-version>`
- Verify:
- check `package.json` (`dependencies` vs `devDependencies` placement)
- run the smallest relevant compile/test command
- Example (`@chainlink/contracts` -> `1.2.0`):
- `npm install @chainlink/contracts@1.2.0`

### Foundry dependencies
- Optional: pull latest submodule state first (all or specific):
- `forge update`
- `forge update lib/chainlink-evm lib/chainlink-ccip`
- Install/update with pinned tag:
- `forge install <org>/<repo>@<tag>`
- For direct dependencies:
- `@chainlink/contracts` equivalent:
- `forge install smartcontractkit/chainlink-evm@contracts-v<version>`
- `@chainlink/contracts-ccip` equivalent:
- `forge install smartcontractkit/chainlink-ccip@contracts-ccip-v<version>`
- Historical note:
- older docs may reference `chainlink-brownie-contracts`; this repo uses `chainlink-evm`.
- After install:
- verify `lib/` points to the expected tag/commit
- verify npm versions in `package.json`
- run `forge build` and relevant tests
- never edit vendored files manually inside `lib/**` or `node_modules/**`

## Change Checklist
Before finishing:
1. Run the smallest relevant compile/test command(s).
2. Regenerate docs if your change affects docs sources.
3. Confirm no accidental edits in unrelated files.
4. Summarize:
- what changed
- what was intentionally not touched
- any residual risk or follow-up

## Known Good Defaults
- Node.js `22.x` is the safe default for workflow parity.
- Prefer `rg` for search.
- Prefer explicit, boring solutions over abstraction-heavy changes.
3 changes: 3 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Claude Code Instructions

All project rules, conventions, and commands are in [`AGENTS.md`](AGENTS.md). Read it before starting any task.
48 changes: 48 additions & 0 deletions api_reference/javascript/DataStreamsLocalSimulatorFork.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
## Functions

<dl>
<dt>
<a href="#requestLinkFromFaucet">
requestLinkFromFaucet(linkAddress, to, amount)
</a>{' '}
⇒ <code>Promise.&lt;string&gt;</code>
</dt>
<dd>
<p>Requests LINK tokens from the faucet and returns the transaction hash</p>
</dd>
<dt>
<a href="#requestNativeFromFaucet">requestNativeFromFaucet(to, amount)</a>
</dt>
<dd>
<p>Requests native coins from the faucet</p>
</dd>
</dl>

<a name="requestLinkFromFaucet"></a>

## requestLinkFromFaucet(linkAddress, to, amount) ⇒ <code>Promise.&lt;string&gt;</code>

Requests LINK tokens from the faucet and returns the transaction hash

**Kind**: global function
**Returns**: <code>Promise.&lt;string&gt;</code> - Promise resolving to the
transaction hash of the fund transfer

| Param | Type | Description |
| ----------- | ------------------- | ------------------------------------------------------- |
| linkAddress | <code>string</code> | The address of the LINK contract on the current network |
| to | <code>string</code> | The address to send LINK to |
| amount | <code>bigint</code> | The amount of LINK to request |

<a name="requestNativeFromFaucet"></a>

## requestNativeFromFaucet(to, amount)

Requests native coins from the faucet

**Kind**: global function

| Param | Type | Description |
| ------ | ------------------- | ------------------------------ |
| to | <code>string</code> | The address to send coins to |
| amount | <code>bigint</code> | The amount of coins to request |
Loading