Skip to content
Open
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
50 changes: 47 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ name: Publish Package to NPM
# workflow fires on the tag push, sanity-checks the tag matches
# package.json, builds, publishes to npm, and creates the GitHub
# Release. It never bumps or tags by itself.
#
# Stable tags such as v0.39.2 publish to npm's latest dist-tag.
# Prerelease tags such as v0.40.0-rc1 publish to a matching prerelease
# dist-tag (rc1) and create a GitHub prerelease. Prereleases must never
# become latest.
on:
workflow_dispatch:
push:
Expand All @@ -32,21 +37,49 @@ jobs:

- run: npm ci

- name: Verify tag matches package.json version
- name: Verify tag and resolve npm dist-tag
id: version
run: |
if [ "${GITHUB_REF_TYPE:-}" != "tag" ]; then
echo "Publish must run from a git tag. Current ref type: ${GITHUB_REF_TYPE:-unknown}" >&2
exit 1
fi

TAG_VERSION="${GITHUB_REF_NAME#v}"
PKG_VERSION="$(node -p "require('./package.json').version")"
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "Tag ($TAG_VERSION) and package.json ($PKG_VERSION) disagree — refusing to publish." >&2
echo "Re-cut the release via scripts/release.sh so the tag and the committed version match." >&2
exit 1
fi

IS_PRERELEASE=false
NPM_DIST_TAG=latest
if [[ "$TAG_VERSION" == *-* ]]; then
IS_PRERELEASE=true
NPM_DIST_TAG="${TAG_VERSION#*-}"
NPM_DIST_TAG="${NPM_DIST_TAG%%+*}"

if [ -z "$NPM_DIST_TAG" ] || [ "$NPM_DIST_TAG" = "latest" ]; then
echo "Invalid prerelease npm dist-tag: '$NPM_DIST_TAG'" >&2
exit 1
fi

if [[ "$NPM_DIST_TAG" =~ ^v?[0-9] ]]; then
echo "Invalid prerelease npm dist-tag '$NPM_DIST_TAG': dist-tags must not look like versions." >&2
exit 1
fi
fi

echo "Tag $GITHUB_REF_NAME matches package.json $PKG_VERSION."
echo "npm dist-tag: $NPM_DIST_TAG"
echo "is_prerelease=$IS_PRERELEASE" >> "$GITHUB_OUTPUT"
echo "npm_dist_tag=$NPM_DIST_TAG" >> "$GITHUB_OUTPUT"

- run: npm run build

- name: Publish to npm
run: npm publish --provenance --access public
run: npm publish --provenance --access public --tag "${{ steps.version.outputs.npm_dist_tag }}"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Expand All @@ -62,6 +95,17 @@ jobs:
if [ -z "$NOTES" ]; then
NOTES="Release $GITHUB_REF_NAME"
fi

NOTES="$NOTES

npm install -g genlayer@${{ steps.version.outputs.npm_dist_tag }}"

RELEASE_FLAGS=()
if [ "${{ steps.version.outputs.is_prerelease }}" = "true" ]; then
RELEASE_FLAGS+=(--prerelease)
fi

gh release create "$GITHUB_REF_NAME" \
--title "$GITHUB_REF_NAME" \
--notes "$NOTES"
--notes "$NOTES" \
"${RELEASE_FLAGS[@]}"
4 changes: 3 additions & 1 deletion .github/workflows/smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
smoke:
name: Testnet Smoke Tests
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 10
continue-on-error: true

steps:
Expand Down Expand Up @@ -41,3 +41,5 @@ jobs:

- name: Run smoke tests
run: npm run test:smoke
env:
CLI_SMOKE_TIMEOUT_MS: 240000
24 changes: 0 additions & 24 deletions .github/workflows/sync-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,30 +72,6 @@ jobs:
rsync -a "${{ github.workspace }}/docs/api-references/" pages/api-references/genlayer-cli/
# Copy README as sibling file (strip badges/emojis)
sed -E '/^\[!\[.*\]\(https:\/\/(img\.shields\.io|dcbadge|badge\.fury)/d' "${{ github.workspace }}/README.md" > pages/api-references/genlayer-cli.mdx
# Write _meta.json
cat > pages/api-references/genlayer-cli/_meta.json << 'METAEOF'
{
"init": "init",
"up": "up",
"stop": "stop",
"new": "new",
"config": "config",
"network": "network",
"deploy": "deploy",
"call": "call",
"write": "write",
"schema": "schema",
"code": "code",
"receipt": "receipt",
"trace": "trace",
"appeal": "appeal",
"appeal-bond": "appeal-bond",
"account": "account",
"staking": "staking",
"localnet": "localnet",
"update": "update"
}
METAEOF
if [ -z "$(git status --porcelain)" ]; then
echo "No changes to commit"
exit 0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/validate-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:

- name: Upload coverage report
if: success() && matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v5.4.3
uses: codecov/codecov-action@v7.0.0
with:
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
# Changelog

## [0.40.0-rc1](https://github.com/genlayerlabs/genlayer-cli/compare/v0.39.1...v0.40.0-rc1) (2026-07-08)

### ⚠ BREAKING CHANGES

* **contracts:** require consensus acceptance for success, not just the leader's execution result (#346)

### Features

* add v0.6 fee-aware commands ([#340](https://github.com/genlayerlabs/genlayer-cli/issues/340)) ([ca083ab](https://github.com/genlayerlabs/genlayer-cli/commit/ca083abbf854960a6638d5af63096b532a03cc5a))
* branch-per-major release model ([#311](https://github.com/genlayerlabs/genlayer-cli/issues/311)) ([6fd2f3a](https://github.com/genlayerlabs/genlayer-cli/commit/6fd2f3a678ce348c92470828b03bdfc596afa9cb)), closes [genlayer-js#172](https://github.com/genlayerlabs/genlayer-js/issues/172)
* **network:** custom network profiles with deployment-file import ([#362](https://github.com/genlayerlabs/genlayer-cli/issues/362)) ([185d22b](https://github.com/genlayerlabs/genlayer-cli/commit/185d22bff86884b330c2037c2875a5d1629ec72b)), closes [#1162](https://github.com/genlayerlabs/genlayer-cli/issues/1162) [#1162](https://github.com/genlayerlabs/genlayer-cli/issues/1162)
* staking validators discovery ([#357](https://github.com/genlayerlabs/genlayer-cli/issues/357)) ([0e76bce](https://github.com/genlayerlabs/genlayer-cli/commit/0e76bcef4524907f80d1567ad688550e24c7192b))
* support fee profiles in contract commands ([#355](https://github.com/genlayerlabs/genlayer-cli/issues/355)) ([6edfcfa](https://github.com/genlayerlabs/genlayer-cli/commit/6edfcfa6d1ad2fcbf761c1ed9f3a194d31243624))
* vesting commands ([#358](https://github.com/genlayerlabs/genlayer-cli/issues/358)) ([7bcc41e](https://github.com/genlayerlabs/genlayer-cli/commit/7bcc41e7a063bd4a628f689bdf4d321b50230aff))

### Bug Fixes

* **contracts:** require consensus acceptance for success, not just the leader's execution result ([#346](https://github.com/genlayerlabs/genlayer-cli/issues/346)) ([6fadcd7](https://github.com/genlayerlabs/genlayer-cli/commit/6fadcd7c9ef181042c823faeec1b7e7fb4d902b2)), closes [#345](https://github.com/genlayerlabs/genlayer-cli/issues/345)
* **docs-sync:** stop overwriting the generated root _meta.json ([#352](https://github.com/genlayerlabs/genlayer-cli/issues/352)) ([f1f1304](https://github.com/genlayerlabs/genlayer-cli/commit/f1f130461dc7d719c9f34086aeb40d8426f0602e)), closes [genlayer-docs#426](https://github.com/genlayerlabs/genlayer-docs/issues/426)
* drop getSlashingAddress from validator-history ([#361](https://github.com/genlayerlabs/genlayer-cli/issues/361)) ([32a0a42](https://github.com/genlayerlabs/genlayer-cli/commit/32a0a42d687a27c633a0ee29b6fbc84842c3cc18)), closes [#344](https://github.com/genlayerlabs/genlayer-cli/issues/344) [#344](https://github.com/genlayerlabs/genlayer-cli/issues/344) [#341](https://github.com/genlayerlabs/genlayer-cli/issues/341)
* fail CLI writes on execution errors ([#345](https://github.com/genlayerlabs/genlayer-cli/issues/345)) ([5d00884](https://github.com/genlayerlabs/genlayer-cli/commit/5d008844ad0b97760bbd025ed5aac61b41b2b881))
* **init:** use backend provider id "google" for Gemini ([#359](https://github.com/genlayerlabs/genlayer-cli/issues/359)) ([561370f](https://github.com/genlayerlabs/genlayer-cli/commit/561370f955f23dc2e1952daac2c42aecb3f3431c)), closes [#271](https://github.com/genlayerlabs/genlayer-cli/issues/271)
* **localnet:** print validator count to stdout ([37519e1](https://github.com/genlayerlabs/genlayer-cli/commit/37519e18b6155bc762fa24ea809a53c3e83ac9a7))
* make git install build lifecycle robust ([#363](https://github.com/genlayerlabs/genlayer-cli/issues/363)) ([a4f8a63](https://github.com/genlayerlabs/genlayer-cli/commit/a4f8a63ae9c945ecf99a707e700857d6f7729df7))
* run CI on v0.39 branch ([#322](https://github.com/genlayerlabs/genlayer-cli/issues/322)) ([e129bab](https://github.com/genlayerlabs/genlayer-cli/commit/e129bab0c471c2d59d360b5ca8c1cb3190774ff8))
* **system:** propagate command-check and version parse fixes to v0.40-dev ([#350](https://github.com/genlayerlabs/genlayer-cli/issues/350)) ([9ebf9e0](https://github.com/genlayerlabs/genlayer-cli/commit/9ebf9e0d1ab5266c58d2e8a274c0b42acc8ad753)), closes [#349](https://github.com/genlayerlabs/genlayer-cli/issues/349)

## 0.39.1 (2026-05-06)

### Bug Fixes
Expand Down
20 changes: 6 additions & 14 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,11 @@ Have ideas for new features or use cases? We're eager to hear them! But first:

## Branch model

This repo uses a branch-per-major release model. There is no `main`.

- **`v0.39`** — current stable major (semver-zero, so 0.39 IS the major; 0.40 would be a major bump that gets its own branch). PRs for bug fixes / non-breaking features target this branch.
- **`v<next>-dev`** — when next-major work is in progress, this branch is open for breaking changes. PRs introducing them target this branch.
- **Older majors** stay for back-ports. Default branch on github.com is whichever major is current stable.

When you fork or clone, the default branch is `v0.39` today. If you have a `main` branch from a previous checkout, delete it locally:

```sh
git checkout v0.39
git branch -D main
git remote prune origin
```
See [docs/BRANCHING.md](docs/BRANCHING.md) for the current release-train model.
In short: independently releasable work may target the stable branch directly;
multi-feature or cross-repo train work uses the active `*-dev` integration
branch and is promoted to the matching stable branch when ready. `main` is only
the default/static GitHub branch.

The previous `staging` branch (beta channel) has been retired. Pre-releases now go through the same release script with an explicit version (`scripts/release.sh 0.39.2-beta.0`).

Expand Down Expand Up @@ -138,4 +130,4 @@ Connect with the GenLayer community to discuss, collaborate, and share insights:
- **[Discord Channel](https://discord.gg/8Jm4v89VAu)**: Our primary hub for discussions, support, and announcements.
- **[Telegram Group](https://t.me/genlayer)**: For more informal chats and quick updates.

Your continuous feedback drives better product development. Please engage with us regularly to test, discuss, and improve the GenLayer CLI.
Your continuous feedback drives better product development. Please engage with us regularly to test, discuss, and improve the GenLayer CLI.
59 changes: 48 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ OPTIONS (deploy):
--contract <contractPath> (Optional) Path to the intelligent contract to deploy
--rpc <rpcUrl> RPC URL for the network
--fees <json> Transaction fee options JSON passed to genlayer-js
--fee-profile <path> Fee profile generated by gltest --fee-profile
--fee-preset <preset> Fee profile appeal posture: low, standard, or high
--appeal-rounds <count> Override fee profile appeal rounds
--fee-value <wei> Explicit fee deposit value
--valid-until <timestamp> Unix timestamp after which the transaction is invalid
--args <args...> Contract arguments (see Argument Types below)
Expand All @@ -187,13 +190,19 @@ OPTIONS (call):
OPTIONS (write):
--rpc <rpcUrl> RPC URL for the network
--fees <json> Transaction fee options JSON passed to genlayer-js
--fee-profile <path> Fee profile generated by gltest --fee-profile
--fee-preset <preset> Fee profile appeal posture: low, standard, or high
--appeal-rounds <count> Override fee profile appeal rounds
--fee-value <wei> Explicit fee deposit value
--valid-until <timestamp> Unix timestamp after which the transaction is invalid
--args <args...> Method arguments (see Argument Types below)

OPTIONS (estimate-fees):
--rpc <rpcUrl> RPC URL for the network
--fees <json> Fee estimate options JSON, or a transaction fee object
--fee-profile <path> Fee profile generated by gltest --fee-profile
--fee-preset <preset> Fee profile appeal posture: low, standard, or high
--appeal-rounds <count> Override fee profile appeal rounds
--include-report Include simulation fee accounting/report in the generated estimate output
--args <args...> Method arguments for simulation-derived estimates

Expand All @@ -205,11 +214,14 @@ EXAMPLES:
genlayer deploy --contract ./my_contract.gpy
genlayer deploy --contract ./my_contract.gpy --args "arg1" "arg2" 123
genlayer deploy --contract ./my_contract.gpy --fees '{"distribution":{"leaderTimeunitsAllocation":"100","validatorTimeunitsAllocation":"200","rotations":["0"]}}'
genlayer deploy --contract ./my_contract.gpy --fee-profile ./artifacts/fee-profile.json
genlayer call 0x123456789abcdef greet --args "Hello World!"
genlayer write 0x123456789abcdef updateValue --args 42
genlayer write 0x123456789abcdef updateValue --fees '{"distribution":{"leaderTimeunitsAllocation":"100","validatorTimeunitsAllocation":"200","rotations":["0"]}}' --args 42
genlayer write 0x123456789abcdef updateValue --fee-profile ./artifacts/fee-profile.json --fee-preset standard --args 42
genlayer estimate-fees
genlayer estimate-fees 0x123456789abcdef updateValue --args 42
genlayer estimate-fees 0x123456789abcdef updateValue --fee-profile ./artifacts/fee-profile.json --json
genlayer write 0x123456789abcdef sendReward --args 0x6857Ed54CbafaA74Fc0357145eC0ee1536ca45A0
genlayer write 0x123456789abcdef setScores --args '[1, 2, 3]'
genlayer write 0x123456789abcdef setConfig --args '{"timeout": 30, "retries": 5}'
Expand All @@ -218,6 +230,28 @@ EXAMPLES:

##### Transaction Fee Options

For reproducible application presets, pass the profile produced by
`gltest --fee-profile`:

```bash
genlayer estimate-fees 0x123456789abcdef settle \
--fee-profile ./artifacts/fee-profile.json \
--fee-preset standard \
--json

genlayer write 0x123456789abcdef settle \
--fee-profile ./artifacts/fee-profile.json \
--fee-preset standard
```

`deploy` reads the profile's `deploy` entry. `write` and targeted
`estimate-fees` read `methods[method]`. The CLI converts the measured profile
entry into SDK fee-estimate options, asks `genlayer-js` for a transaction fee
preset, then sends that preset with the transaction. `--fee-preset` controls the
default appeal posture (`low`, `standard`, or `high`); use `--appeal-rounds`
for an explicit override. `--fees` can still be provided alongside
`--fee-profile` to override individual values, including `messageAllocations`.

`--fees` accepts the same transaction fee object as `genlayer-js`. Quote large
integer values as strings to preserve precision. `messageAllocations[].messageType`
may be `"internal"`, `"external"`, `0`, or `1`.
Expand Down Expand Up @@ -253,29 +287,32 @@ preset for reproducible gas-unit debugging.

The `--args` option automatically detects and converts values to the correct type:

| Type | Syntax | Example |
|------|--------|---------|
| Boolean | `true`, `false` | `--args true false` |
| Null | `null` | `--args null` |
| Integer | numeric value | `--args 42 -1` |
| Hex integer | `0x` prefix | `--args 0x1a` |
| String | any other value | `--args hello "multi word"` |
| Address | 40 hex chars with `0x` or `addr#` prefix | `--args 0x6857...a0` or `--args addr#6857...a0` |
| Bytes | `b#` prefix + hex | `--args b#deadbeef` |
| Array | JSON array in quotes | `--args '[1, 2, "three"]'` |
| Dict | JSON object in quotes | `--args '{"key": "value"}'` |
| Type | Syntax | Example |
| ----------- | ---------------------------------------- | ----------------------------------------------- |
| Boolean | `true`, `false` | `--args true false` |
| Null | `null` | `--args null` |
| Integer | numeric value | `--args 42 -1` |
| Hex integer | `0x` prefix | `--args 0x1a` |
| String | any other value | `--args hello "multi word"` |
| Address | 40 hex chars with `0x` or `addr#` prefix | `--args 0x6857...a0` or `--args addr#6857...a0` |
| Bytes | `b#` prefix + hex | `--args b#deadbeef` |
| Array | JSON array in quotes | `--args '[1, 2, "three"]'` |
| Dict | JSON object in quotes | `--args '{"key": "value"}'` |

Large numbers that exceed JavaScript's safe integer range are automatically handled as BigInt to preserve precision.

##### Deploy Behavior

- If `--contract` is specified, the command will **deploy the given contract**.
- If `--contract` is omitted, the CLI will **search for scripts inside the `deploy` folder**, sort them, and execute them sequentially.

##### Call vs Write

- `call` - Calls a contract method without sending a transaction or changing the state (read-only)
- `write` - Sends a transaction to a contract method that modifies the state

##### Schema

- `schema` - Retrieves the contract schema

#### Transaction Operations
Expand Down
Loading
Loading