Generated TypeScript bindings can become stale when the underlying Soroban contract ABI changes. Glassbox detects this automatically by embedding a cryptographic ABI hash into every generated file and comparing it against the current source ABI on demand.
Every file produced by glassbox generate-bindings begins with a structured
comment block:
/* @glassbox-bindings-meta
* abi-hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
* contract-id: CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQAHHAGCN4B2
* generated: 2026-05-30T12:00:00Z
* glassbox: 1.2.3
*/| Field | Description |
|---|---|
abi-hash |
SHA-256 of the canonical JSON representation of the contract spec |
contract-id |
Stellar contract ID (empty when not provided at generation time) |
generated |
RFC 3339 UTC timestamp of when the bindings were generated |
glassbox |
Version of the glassbox binary that generated the bindings |
The ABI hash is computed by serialising the contract spec to the canonical
JSON format (the same output as glassbox abi --format json) and taking its
SHA-256 digest. Because the canonical JSON is deterministic, the hash changes
if and only if the ABI changes — regardless of whether the source was a WASM
binary or a JSON/XDR spec file.
glassbox check-bindings reads the abi-hash field from each generated file
and compares it against the hash computed from the current source ABI. A file
is reported as:
| Status | Meaning |
|---|---|
fresh |
The stored hash matches the current ABI — no action needed |
stale |
The stored hash differs — the ABI has changed since generation |
missing |
The file does not exist in the output directory |
no-metadata |
The file exists but has no @glassbox-bindings-meta header (generated by an older glassbox version) |
Use glassbox generate-bindings as usual. Metadata headers are embedded by
default:
# From a compiled WASM binary
glassbox generate-bindings contract.wasm \
--output ./src/generated \
--package my-contract
# From a JSON ABI file
glassbox generate-bindings \
--spec-file contract-abi.json \
--output ./src/generated \
--package my-contractTo opt out of metadata embedding (e.g. for reproducible snapshot tests):
# Not recommended for production workflows — disables staleness detection
glassbox generate-bindings contract.wasm --output ./src/generated --no-embed-metadata# Check against a WASM binary
glassbox check-bindings contract.wasm --output ./src/generated
# Check against a JSON ABI file
glassbox check-bindings --spec-file contract-abi.json --output ./src/generatedExample output when bindings are up-to-date:
Binding directory : ./src/generated
Source ABI hash : e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
✓ types.ts fresh
✓ metadata.ts fresh
✓ client.ts fresh
✓ Glassbox-integration.ts fresh
✓ index.ts fresh
✓ package.json fresh
✓ README.md fresh
[OK] All bindings are up-to-date.
Example output when bindings are stale:
Binding directory : ./src/generated
Source ABI hash : a1b2c3d4e5f6...
✗ types.ts stale
ABI hash mismatch: stored=e3b0c442 current=a1b2c3d4
✗ metadata.ts stale
...
[STALE] 7 file(s) are out-of-date. Run with --regenerate to update.
Pass --json to get a machine-readable report:
glassbox check-bindings --spec-file abi.json --output ./src/generated --json{
"outputDir": "./src/generated",
"sourceABIHash": "a1b2c3d4...",
"isStale": true,
"staleCount": 7,
"files": [
{
"path": "types.ts",
"status": "stale",
"storedHash": "e3b0c442...",
"currentHash": "a1b2c3d4...",
"generatedAt": "2026-05-30T12:00:00Z",
"reason": "ABI hash mismatch: stored=e3b0c442 current=a1b2c3d4"
}
]
}| Code | Meaning |
|---|---|
0 |
All bindings are up-to-date |
1 |
One or more bindings are stale, missing, or have no metadata |
2 |
A usage or validation error occurred |
Pass --regenerate to automatically regenerate any stale or missing files:
glassbox check-bindings contract.wasm \
--output ./src/generated \
--regenerate \
--package my-contract \
--network testnetRegeneration flags (only used when --regenerate is set):
| Flag | Default | Description |
|---|---|---|
--package |
input filename | npm package name for the generated bindings |
--network |
testnet |
Stellar network (testnet, mainnet, futurenet) |
--runtime |
node |
Target runtime: node, browser, or universal |
--contract-id |
(empty) | Stellar contract ID to embed |
--debug-metadata |
false |
Include ABI debug metadata wrappers |
Add a pre-commit check or a Makefile target:
.PHONY: check-bindings
check-bindings:
glassbox check-bindings contract.wasm \
--output ./src/generated \
--package my-contract
.PHONY: update-bindings
update-bindings:
glassbox check-bindings contract.wasm \
--output ./src/generated \
--package my-contract \
--regenerateUse the non-zero exit code to fail the build when bindings are stale:
# GitHub Actions example
- name: Check TypeScript bindings are up-to-date
run: |
glassbox check-bindings contract.wasm \
--output ./src/generated \
--json | tee binding-report.json
# Exit code 1 fails the step automatically.#!/bin/sh
# .git/hooks/pre-commit
glassbox check-bindings contract.wasm --output ./src/generated
if [ $? -ne 0 ]; then
echo "TypeScript bindings are stale. Run 'make update-bindings' to regenerate."
exit 1
fi"no @glassbox-bindings-meta header found"
The binding files were generated by an older version of glassbox that did not embed metadata headers. Regenerate them:
glassbox generate-bindings contract.wasm --output ./src/generated --package my-contractHash mismatch after a no-op ABI change
If the ABI hash changes even though you believe the contract interface is unchanged, inspect the canonical JSON to see what differs:
glassbox abi --format json contract.wasmMinor changes such as reordering functions, adding documentation strings, or changing struct field order will all produce a different hash.
Bindings are always reported as stale in CI
Ensure the same WASM binary (or spec file) is used for both generation and validation. If the WASM is rebuilt between steps, the ABI hash will differ even if the interface is logically identical.