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
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ stellar registry deploy \
-- \
--param1 value1

# Install the deployed contract locally as a stellar-cli alias
stellar registry install my-contract-instance
# Create a local stellar-cli alias for the deployed contract
stellar registry create-alias my-contract-instance
```

Use `--help` on any command for full usage. See the crate README at
Expand Down Expand Up @@ -74,6 +74,10 @@ It separates **Wasm publication** (reusable code), **contract deployment**
(instances), and **local installation** (CLI aliases). The contracts themselves
live in [stellar-registry/contracts](https://github.com/stellar-registry/contracts).

## Agent skill

[`skills/stellar-registry`](./skills/stellar-registry/SKILL.md) is an [Agent Skill](https://skills.stellar.org/) that teaches coding agents the registry CLI workflow and the `import_contract!` / `import_contract_client!` / `import_asset!` macros.

## Documentation

- [CLI Commands](https://scaffoldstellar.com/docs/cli)
Expand Down
21 changes: 10 additions & 11 deletions crates/stellar-registry-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,27 @@ stellar registry deploy \
--wasm-name <NAME> \
[--version <VERSION>] \
-- \
[CONSTRUCTOR_FUNCTION] [CONSTRUCTOR_ARGS...]
[CONSTRUCTOR_ARGS...]
```

Options:
- `--contract-name`: Name to give this contract instance (required)
- `--wasm-name`: Name of the published contract to deploy (required)
- `--version`: Specific version of the published contract to deploy (optional, defaults to most recent version)
- `CONSTRUCTOR_FUNCTION`: Optional constructor function name if contract implements initialization
- `CONSTRUCTOR_ARGS`: Optional arguments for the constructor function
- `CONSTRUCTOR_ARGS`: Arguments for the contract's `__constructor`, as `--arg-name value` (run with `-- --help` to list them)

Note: Use `--` to separate CLI options from constructor function and arguments.
Note: Use `--` to separate CLI options from constructor arguments.

### Install
### Create alias

Install a deployed contract as an alias to be used by `stellar-cli`:
Create a local alias for a deployed contract, to be used by `stellar-cli`:
```bash
stellar registry install <CONTRACT_NAME>
stellar registry create-alias <CONTRACT_NAME> [LOCAL_NAME]
```

Options:
- `CONTRACT_NAME`: Name of the deployed contract to install (required)
- `CONTRACT_NAME`: Name of the deployed contract (required)
- `LOCAL_NAME`: Alias to create (optional, defaults to the registry name)

## Configuration

Expand Down Expand Up @@ -106,15 +106,14 @@ stellar registry deploy \
--wasm-name token \
--version "1.0.0" \
-- \
initialize \
--name "My Token" \
--symbol "MTK" \
--decimals 7
```

3. Install the deployed contract:
3. Create a local alias for the deployed contract:
```bash
stellar registry install my-token
stellar registry create-alias my-token
```

Then can interact with the contract with `stellar-cli`:
Expand Down
136 changes: 136 additions & 0 deletions skills/stellar-registry/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
name: stellar-registry
description: Publish, deploy, and reuse named Soroban smart contracts through the Stellar Registry. Use when publishing a contract's wasm with a name and semantic version, deploying a named contract instance, looking up a contract id by name, aliasing a registry contract for `stellar contract invoke`, or making cross-contract calls from Rust with `stellar_registry::import_contract!`, `import_contract_client!`, or `import_asset!` (including XLM and other Stellar Asset Contracts).
---

# Stellar Registry

The Stellar Registry is an on-chain contract that gives Soroban contracts human-readable names:

- **Wasms** are published code with a name and semantic version (`my-token@1.2.0`).
- **Contracts** are deployed instances with a name (`my-token-instance`), no version.

Two tools use it:

1. **`stellar registry` CLI plugin**: publish, deploy, look up, upgrade.
2. **`stellar-registry` Rust crate**: macros that turn a registry name into a typed client at build time, so cross-contract calls need no hardcoded addresses.

Browse what's already published at https://stellar.rgstry.xyz (`/wasms`, `/contracts`).

## Setup

```bash
# Requires the Stellar CLI (`stellar`). The registry is a plugin for it:
cargo install --locked stellar-registry-cli # or: cargo binstall stellar-registry-cli

stellar keys generate alice --network testnet --fund # skip if you have an identity
stellar keys use alice
stellar network use testnet
```

Every command needs a source account and network. Set defaults as above, or pass `--source alice --network testnet`.

## Names: verified vs. `unverified/`

Names are `name` or `channel/name`. The default (verified) registry is **managed**: a new name must be approved by the registry manager before it can be published or deployed. For hackathons and experiments, **use the `unverified/` channel**, which is open to anyone:

```bash
--wasm-name unverified/my-token # publish/deploy under the open channel
--contract-name unverified/my-token
```

Well-known verified names (e.g. `registry`, `unverified` itself) can be read by anyone without a prefix.

## CLI workflow

```bash
stellar contract build # produces target/wasm32v1-none/release/my_token.wasm

# 1. Publish the wasm (name + version; both default to contract metadata if omitted)
stellar registry publish \
--wasm target/wasm32v1-none/release/my_token.wasm \
--wasm-name unverified/my-token --binver 0.1.0

# 2. Deploy a named instance. After `--`, pass the __constructor's args as flags
stellar registry deploy \
--contract-name unverified/my-token --wasm-name unverified/my-token \
-- --admin alice --decimal 7
# (`-- --help` prints the constructor's arguments; `--version` pins a wasm version)

# 3. Use it from the Stellar CLI by name
stellar registry create-alias unverified/my-token my-token
stellar contract invoke --id my-token -- --help

# Look things up
stellar registry fetch-contract-id unverified/my-token
stellar registry current-version unverified/my-token
stellar registry download unverified/my-token -o my_token.wasm

# Ship a new version to an existing instance
stellar registry publish --wasm ... --wasm-name unverified/my-token --binver 0.2.0
stellar registry upgrade --contract-name unverified/my-token --wasm-name unverified/my-token
```

Try any write with `--dry-run` first (publish, publish-hash, register-contract, rename/update commands). Full command list: [references/cli.md](references/cli.md).

## Calling registry contracts from Rust

Add the crate to your contract:

```toml
[dependencies]
stellar-registry = "0.1"
```

Pick the macro by what you have:

| You have… | Use | You get |
|---|---|---|
| A **deployed contract name** | `import_contract!(env, name)` | A client already bound to its address |
| XLM or a classic asset (`xlm`, `"USDC:G..."`) | `import_contract!(env, xlm)` | `token::TokenClient` for its SAC |
| A **published wasm name** (+ optional version) | `import_contract_client!(name)` | A `name::Client` module; you supply the address |
| An asset, and you want its SAC id/admin client | `import_asset!("USDC:G...")` | Module with `contract_id`, `token_client`, `stellar_asset_client` |

```rust
use soroban_sdk::{contract, contractimpl, Address, Env};

#[contract]
pub struct Tipper;

#[contractimpl]
impl Tipper {
pub fn tip(env: &Env, from: Address, amount: i128) {
from.require_auth();
let xlm = stellar_registry::import_contract!(env, xlm);
xlm.transfer(&from, &env.current_contract_address(), &amount);
}

pub fn lookup(env: &Env, name: soroban_sdk::String) -> Address {
let registry = stellar_registry::import_contract!(env, registry);
registry.fetch_contract_id(&name)
}
}
```

Before calling a contract's methods, list them with `stellar contract info interface --id <C...>` (get the id from `stellar registry fetch-contract-id <name>`).

**Build with the network set.** The macros resolve names at build time, reading `STELLAR_NETWORK`, which **defaults to `local`**:

```bash
STELLAR_NETWORK=testnet stellar contract build
```

Details (caching, offline builds, hyphenated names, versions, unit-testing SAC calls): [references/macros.md](references/macros.md).

## Common pitfalls

- **Authorization failure on publish or deploy**: you used a bare name on the managed registry. Prefix with `unverified/`.
- **`Error(Contract, #N)` from the registry**: common codes are `#2` no such version, `#3` wasm name taken by another author, `#4` no such contract, `#5` contract name already deployed, `#8` version must be greater than the latest, `#9` invalid name (≤64 chars, ASCII alphanumeric/`-`/`_`, starts with a letter, not a Rust keyword), `#11` these exact wasm bytes were already published.
- **`upgrade` fails**: the registry calls the contract's own `upgrade(wasm_hash)` function, so the contract must implement one. If it exposes `admin()`, that admin must sign.
- **Macro resolves the wrong address or can't find a contract**: `STELLAR_NETWORK` wasn't set at build time. It defaults to `local`, so asset/XLM contract ids are computed for the wrong network without any error.
- **`unresolved import super` / `no soroban_sdk in the root` from `import_contract_client!`**: add `use soroban_sdk;` to the module where you call it. `import_contract!` and `import_asset!` don't need this.
- **Macro says `stellar` or the registry plugin is missing / too old**: the macros shell out to `stellar registry` during `cargo build`. Run `cargo install stellar-registry-cli --force`.
- **Hyphens or channels in a macro name**: use a string literal, `import_contract!(env, "unverified/my-token")`. The module is named with `-` replaced by `_`.
- **Redeployed a contract but still calling the old one**: the address is baked in at build time. `cargo clean` (or delete `target/stellar/<network>/deployed/`) and rebuild.
- **Contract flagged as compromised**: `fetch-contract-id`, `create-alias`, and `import_contract!` refuse it. This is intentional; use `--force` on the CLI only if you're sure.
- **There is no `stellar registry install`**. Use `create-alias`.
62 changes: 62 additions & 0 deletions skills/stellar-registry/references/cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# `stellar registry` command reference

Every command also accepts the standard Stellar CLI network and signing flags: `--source-account/--source`, `--network`, `--rpc-url`, `--network-passphrase`, `--inclusion-fee`, `--sign-with-key`, `--sign-with-ledger`, `--sign-with-lab`. These fall back to `STELLAR_ACCOUNT`, `STELLAR_NETWORK`, etc., and to `stellar keys use` / `stellar network use` defaults. `STELLAR_REGISTRY_CONTRACT_ID` overrides the root registry address.

Any `<name>` can be channel-prefixed (`unverified/<name>`) to target a sub-registry instead of the managed root registry.

## Wasms (published code)

| Command | Purpose | Key arguments |
|---|---|---|
| `publish` | Upload a wasm and publish it under a name + semver | `--wasm <PATH>`, `--wasm-name <NAME>`, `--binver <VERSION>` (both read from contract metadata if omitted), `-a/--author`, `--dry-run` |
| `publish-hash` | Publish a wasm that's already uploaded on-chain | `--wasm-hash <HEX>`, `--wasm-name`, `--version`, `-a/--author`, `--dry-run` |
| `current-version <WASM_NAME>` | Latest published version | |
| `fetch-hash <WASM_NAME>` | Hash of a published wasm | `--version` |
| `download <WASM_NAME>` | Fetch the wasm bytes | `--version`, `-o/--out-file` (default stdout) |

Versions must strictly increase for a given name. Only the original author can publish new versions of a name.

## Contracts (deployed instances)

| Command | Purpose | Key arguments |
|---|---|---|
| `deploy` | Deploy a published wasm and register the instance by name | `--contract-name` (alias `--deploy-as`), `--wasm-name`, `--version`, `--deployer`, `-- <constructor args>` |
| `deploy-unnamed` | Deploy a published wasm without registering a name | `--wasm-name`, `--version`, `--salt <HEX32>`, `--deployer`, `-- <constructor args>` |
| `register-contract` | Name an already-deployed contract | `--contract-name`, `--contract-address <C...>`, `--owner`, `--dry-run` |
| `fetch-contract-id <NAME>` | Resolve a name to its `C...` address | `--force` (return it even if flagged compromised) |
| `create-alias <NAME> [LOCAL_NAME]` | Save a local `stellar contract alias` for use with `--id <alias>` | `-f/--force` (overwrite; allow flagged contracts) |
| `upgrade` | Upgrade a named contract to a published wasm version | `--contract-name`, `--wasm-name`, `--version` (default latest) |
| `rename-contract` | Rename a registration | `--contract-name`, `--new-name`, `--dry-run` |
| `update-contract-address` | Point a name at a different address | `--contract-name`, `--new-address`, `--dry-run` |
| `update-contract-owner` | Transfer ownership of a registration | `--contract-name`, `--new-owner`, `--dry-run` |
| `version` | Print the plugin version | |

### Constructor arguments

Anything after `--` on `deploy` / `deploy-unnamed` is passed to the contract's `__constructor` as `--arg value` flags. Don't name the function; it's added for you. Addresses can be identity names (`--admin alice`). Run with `-- --help` to print the constructor's signature. Contracts without a constructor take no arguments.

### Upgrades

`upgrade` looks up the wasm hash for `--wasm-name`/`--version`, then calls the named contract's `upgrade(wasm_hash)` function. If the contract exposes `admin()`, the registry requires that admin's signature. Otherwise the contract's own `upgrade` must enforce authorization.

## Examples

```bash
# Publish to the open channel and deploy with a constructor
stellar registry publish --wasm target/wasm32v1-none/release/counter.wasm \
--wasm-name unverified/counter --binver 1.0.0
stellar registry deploy --contract-name unverified/my-counter \
--wasm-name unverified/counter -- --owner alice

# Deploy a specific older version
stellar registry deploy --contract-name unverified/counter-v1 \
--wasm-name unverified/counter --version 1.0.0 -- --owner alice

# Give an existing contract a registry name
stellar registry register-contract --contract-name unverified/my-dao \
--contract-address CABC...XYZ

# Use a registry contract from the CLI
stellar registry create-alias unverified/my-counter counter
stellar contract invoke --id counter -- increment
```
Loading
Loading