sdkt-rpc 2.7.0

Soroban JSON-RPC client, endpoint configurations and network connectivity wrapper.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
<h1 align="center">Soroban DevKit (<code>sdkt</code>)</h1>

<p align="center">
  <a href="https://github.com/SaboLabs/soroban-devkit/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/SaboLabs/soroban-devkit/ci.yml?branch=main&label=CI" alt="CI"></a>
  <a href="https://github.com/SaboLabs/soroban-devkit/actions/workflows/release.yml"><img src="https://img.shields.io/github/actions/workflow/status/SaboLabs/soroban-devkit/release.yml?branch=main&label=Release" alt="Release"></a>
  <a href="https://img.shields.io/crates/v/sdkt-cli"><img src="https://img.shields.io/crates/v/sdkt-cli?label=crates.io" alt="crates.io"></a>
  <a href="https://github.com/SaboLabs/soroban-devkit/releases"><img src="https://img.shields.io/github/v/release/SaboLabs/soroban-devkit?label=release" alt="release"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
</p>

<p align="center">
  Release-assurance and operational verification toolkit for <strong>Stellar/Soroban</strong> smart contracts.<br>
  Inspect, verify, audit, compare upgrades, and validate deployed contracts — with an aggregated release decision.
</p>

<p align="center">
  <strong>Website:</strong> <a href="https://sabolabs.github.io/soroban-devkit/">sabolabs.github.io/soroban-devkit</a> — landing +
  <a href="https://sabolabs.github.io/soroban-devkit/playground/">in-browser WASM inspector</a>
  (contract bytes stay in the tab). Source: <a href="website/"><code>website/</code></a>.
</p>

---

`sdkt` is a release-assurance and operational verification toolkit for Soroban smart contracts. It consolidates the checks that answer "is this build safe to release?" — artifact inspection, static security audit, upgrade-safety diff, deployed-contract verification, and contract health — into a single CLI with an aggregated release decision, and covers the surrounding day-to-day work (XDR decoding, storage/TTL analysis, events, network profiles, build and deployment orchestration) so developers stop juggling 5+ separate tools.

## The Problem

Before shipping a contract upgrade, a developer has to answer several unrelated questions with unrelated tools: does the new WASM break the ABI callers depend on? Does the deployed contract actually match my build? Is the storage TTL about to expire? Did the source pass a security review? `sdkt` answers all of them from one CLI and aggregates the results into a single machine-readable release decision (`sdkt release-assurance`). It also spans the rest of the lifecycle — scaffold, build, deploy, invoke — with upgrade-safety guards applied on the write path.

## Capabilities

`sdkt` spans the full read-only **and** mutating contract lifecycle:

- **Release assurance** — one command aggregates artifact checks, static audit, upgrade-safety diff, deployed verification, and contract health into a single `PASS`/`REVIEW`/`FAIL` release decision (`sdkt release-assurance`); the same engine is available as a GitHub Action for CI and release gating.
- **Inspect & decode** — base64 XDR decoding, contract ABI + storage inspection, event exploration.
- **Analyze** — storage TTL / rent visibility, Instance / Persistent / Temporary classification, offline ABI/function/event/type WASM diffing.
- **Secure** — static analysis of contract source (`AUTH-001/002/003/004`, `MOVE-001`) and an upgrade-safety verdict for safe contract upgrades.
- **Verify deployed reality** — on-chain WASM hash vs local artifact (`sdkt verify`), unified contract posture (`sdkt health`).
- **Build & ship** — typed transaction envelope builder, simulate, **native transaction signing**, submit, identity/keystore management, multi-contract workspace topological deployments, and upgrade breaking-change guards.

Most commands are **offline**; only on-chain reads (`inspect`, `storage`, `tx`, `events`, `account`, `fee`, `wasm metadata`) need an RPC endpoint.

## Release assurance

`sdkt release-assurance` is the one command that answers the release question. It
is **read-only** — it never signs, submits, deploys, extends TTL, or mutates any
state — and it aggregates five checks on one candidate artifact into a single
release status.

Where it fits:

```
source → artifact → security → upgrade → deployed reality → health → release decision
```

| Section | What it checks | Source |
|---------|----------------|--------|
| Artifact | the candidate WASM's hash, size and spec; optional size policy | local file |
| Security | static audit of contract source (same engine as `sdkt audit`) | `--audit <path>` |
| Upgrade Safety | breaking-change verdict against the previous artifact | `--previous-wasm` |
| Verification | on-chain WASM hash vs the local artifact | `--contract` + RPC |
| Contract Health | storage/TTL posture and verdict | `--contract` + RPC |

Each section reports `PASS` / `REVIEW` / `FAIL` / `SKIPPED`, then aggregates
deterministically: any `FAIL`/`ERROR` makes `release_status` `FAIL` (exit 1),
otherwise a `REVIEW`/`SKIPPED` yields `REVIEW` (exit 0). On-chain sections are
**skipped** when `--contract` is omitted, and a skip is never flattened into
`PASS`. That aggregate status is what a CI step gates on.

```bash
# Candidate vs previous artifact: offline artifact + upgrade-safety checks:
sdkt release-assurance \
  --wasm target/wasm32v1-none/release/my_contract.wasm \
  --previous-wasm deployed/my_contract.wasm

# Machine-readable output, plus the on-chain sections once you pass --contract:
sdkt release-assurance \
  --wasm target/wasm32v1-none/release/my_contract.wasm \
  --previous-wasm deployed/my_contract.wasm \
  --contract <CONTRACT_ID> \
  --rpc-url https://soroban-testnet.stellar.org \
  --format json
```

```text
Soroban Release Assurance
────────────────────────
Artifact        PASS
Security        SKIPPED
Upgrade Safety  FAIL
Verification    SKIPPED
Contract Health SKIPPED

RELEASE STATUS  FAIL

Reasons:
  - Upgrade Safety: FAIL
```

Add `--audit <path>` to include the source security section, `--contract <C…>`
(read-only) to include deployed verification and health, and `--max-size-bytes`
/ `--max-growth-pct` to enforce an operator-supplied size policy (a growth cap
requires `--previous-wasm`).

`sdkt` does not release, sign, or deploy anything on your behalf — the decision
is evidence for *your* release process. For CI, the same command is available as
a reusable GitHub Action: see [docs/ci-cd.md](docs/compatibility/ci-cd.md).

## Feature Highlights

| Capability | Command |
|------------|---------|
| **Aggregated release decision** (artifact + audit + upgrade + verification + health) | `sdkt release-assurance` |
| Decode base64 XDR (`ScVal`, `TransactionEnvelope`, `ContractEvent`) | `sdkt decode` |
| Inspect contract ABI + storage | `sdkt inspect`, `sdkt storage check` |
| Storage TTL / rent analysis | `sdkt storage analyze`, `sdkt storage estimate` |
| Transaction inspect / simulate / submit / build | `sdkt tx *` |
| Event explorer | `sdkt events` |
| Account balances + signers | `sdkt account` |
| Dynamic fee estimate | `sdkt fee estimate` |
| Multi-contract Orchestration | `sdkt build`, `sdkt project deploy` |
| WASM Operations | `sdkt wasm inspect`, `sdkt wasm metadata`, `sdkt wasm cache`, `sdkt verify`, `sdkt health` |
| Offline WASM diff + upgrade-safety verdict | `sdkt diff --upgrade-safety` |
| Static security audit | `sdkt audit` |
| ED25519 keystore | `sdkt identity` |
| Named network profiles | `sdkt network` |
| Project scaffolding | `sdkt init` |
| Deploy (with `--deny-breaking` guard) | `sdkt deploy` |
| Contract invocation (read-only) | `sdkt call` |
| Contract invocation (state-changing, end-to-end) | `sdkt invoke` |

## Quick Start

Running `sdkt` takes under five minutes. Pick an install method, verify, then
run your first command.

### 1. Install

Choose **one** of the following methods.

#### Recommended — install.sh (no Rust toolchain needed)

```bash
curl -fsSL https://raw.githubusercontent.com/SaboLabs/soroban-devkit/main/install.sh | bash
```

The script detects your OS/arch, downloads the matching release binary,
verifies its SHA-256 checksum, and installs `sdkt` to `~/.local/bin/sdkt`.

#### Alternative — Manual GitHub Release download

1. Open the [Releases](https://github.com/SaboLabs/soroban-devkit/releases)
   page and download the latest release for your platform:

   | Platform | Asset |
   |----------|-------|
   | Linux (x86_64) | `sdkt-x86_64-unknown-linux-gnu.tar.gz` |
   | Linux (aarch64) | `sdkt-aarch64-unknown-linux-gnu.tar.gz` |
   | macOS (Intel) | `sdkt-x86_64-apple-darwin.tar.gz` |
   | macOS (Apple Silicon) | `sdkt-aarch64-apple-darwin.tar.gz` |
   | Windows (x86_64) | `sdkt-x86_64-pc-windows-msvc.zip` |

2. Extract and run:

   **Linux/macOS:**

   ```bash
   tar -xzf sdkt-x86_64-unknown-linux-gnu.tar.gz   # Linux x86_64
   chmod +x sdkt
   ./sdkt --version
   # Optional: make it available system-wide
   sudo mv sdkt /usr/local/bin/
   ```

   **Windows:** use `sdkt-x86_64-pc-windows-msvc.zip` from the
   GitHub Release. Alternatively, install from crates.io or source:

   ```powershell
   cargo install sdkt-cli
   sdkt --version
   ```

   > **Version note:** the GitHub Release carries the current repository
   > release (v2.7.0). crates.io currently publishes **v2.5.0**, so
   > `cargo install sdkt-cli` installs v2.5.0 — which lacks the WASM size
   > policy, the `sdkt health` critical-exit fix, `sdkt-agent`, and the
   > Windows zip. For v2.7.0 use the release binary, or build from source
   > (below).

#### Alternative — Build from source (requires Rust 1.88.0+)

```bash
git clone https://github.com/SaboLabs/soroban-devkit
cd soroban-devkit
cargo install --path crates/sdkt-cli
sdkt --version
```

### 2. Verify and explore

```bash
sdkt --version
# sdkt <version>

sdkt --help
# Commands:
#   decode    Decode base64-encoded XDR to JSON
#   wasm      Manage WASM metadata and caching
#   diff      Offline diff of two contract WASM files
#   audit     Static security analysis of a Soroban contract source file
#   init      Initialize a new Soroban contract project
#   deploy    Deploy a contract (Upload WASM + Instantiate)
#   ... (run `sdkt --help` to see all)
```

A successful `sdkt --version` means the binary is installed and on your `PATH`.

### Shell completions

Generate completion scripts for your shell and source them:

```bash
# bash
sdkt completions bash > ~/.local/share/bash-completion/completions/sdkt
# zsh
sdkt completions zsh > "${fpath[1]}/_sdkt"
# fish
sdkt completions fish > ~/.config/fish/completions/sdkt.fish
# powershell
sdkt completions powershell > sdkt.ps1
# then in your profile: . ./sdkt.ps1
```

Supported shells: `bash`, `zsh`, `fish`, `powershell` (also `elvish`).

### 3. Your first command (offline)

**No install:** drop a `.wasm` on the
[Web Playground](https://sabolabs.github.io/soroban-devkit/playground/)
(ContractSpec / exports / hash; bytes never leave the browser).

**CLI:** inspect a compiled contract WASM that ships with the repo:

```bash
sdkt wasm inspect crates/sdkt-cli/tests/fixtures/us_old.wasm
```

Then follow the guided walkthrough in
[docs/quick-start.md](docs/getting-started/quick-start.md) — it covers inspect, audit, and
upgrade-safety diff step by step.

## Use Cases

- **Decide whether a release is safe** — compare the candidate contract artifact
  with its previous version, check upgrade compatibility and any release
  constraints, and get evidence for the release decision in one aggregated report
  (`sdkt release-assurance`). Read-only: it never signs or deploys.
- **Inspect Soroban WASM** — read ABI, functions, events, and metadata from any
  compiled contract, offline (`sdkt wasm inspect`).
- **Verify deployed reality** — confirm a deployed contract matches your local
  build, and check its health (`sdkt verify`, `sdkt health`).
- **Compare contract upgrades safely** — diff two WASM files and get a
  breaking-change verdict before deploying (`sdkt diff --upgrade-safety`).
- **Audit contracts offline** — static security analysis of contract source with
  no network or secrets (`sdkt audit`).
- **Scaffold new projects** — generate a ready-to-build Soroban contract
  (`sdkt init`).
- **Deploy with upgrade protection** — upload and instantiate, aborting on a
  non-backwards-compatible upgrade (`sdkt deploy --deny-breaking`).

### From scaffold to deployment

A typical first-contract workflow:

```bash
# 1. Create a new contract project
sdkt init my-contract --minimal
cd my-contract

# 2. Build the contract into a Soroban WASM
#    Output: target/wasm32v1-none/release/<project>.wasm
sdkt build

# 3. Generate a local signing identity
sdkt identity generate my-deployer

# 4. Configure Testnet (one-time setup)
sdkt network add testnet \
  --rpc-url https://soroban-testnet.stellar.org \
  --passphrase "Test SDF Network ; September 2015" \
  --friendbot https://friendbot.stellar.org

# 5. Fund your identity (Testnet only)
#    Copy the public key from `sdkt identity show my-deployer` and paste it at:
#    https://friendbot.stellar.org
#    OR use the CLI directly:
sdkt identity fund my-deployer --network-profile testnet

# 6. Generate a 20-byte salt (40 hex characters)
openssl rand -hex 20

# 7. Deploy to Testnet
sdkt deploy \
  --wasm target/wasm32v1-none/release/my_contract.wasm \
  --salt <paste-hex-from-step-6> \
  --identity my-deployer \
  --network-profile testnet

# 8. Invoke a contract function (state-changing: sequence → simulate → sign → submit → poll)
sdkt invoke <CONTRACT_ID> increment --args u32:1 --identity my-deployer --network-profile testnet
```

For a detailed explanation of each step, see [Deploy a single contract](#deploy-a-single-contract).

## Installation (details)

Full options — including the `wasm-plugins` / `plugins` feature flags,
installing from crates.io, and updating — are in
[docs/installation.md](docs/getting-started/installation.md).

### Extensibility & Plugins

The `sdkt audit` static analysis engine supports third-party plugins.

- **`wasm-plugins` (Recommended):** Build with `cargo install --path crates/sdkt-cli --features wasm-plugins` to load platform-independent, sandboxed `.wasm` plugins.
- **`plugins`:** Build with `--features plugins` to load native shared libraries (`.so`, `.dylib`).

See [`docs/plugin-authoring.md`](docs/plugins/plugin-authoring.md) for how to build or use custom rules.

## Commands

| Command | Purpose |
|---------|---------|
| `sdkt release-assurance --wasm <file> [--previous-wasm <file>] [--audit <path>] [--contract <id>] [--format json]` | Aggregated read-only release decision: artifact + security + upgrade safety + deployed verification + health. Never signs or mutates. |
| `sdkt decode <xdr>` | Decode base64 XDR (`--type ScVal|TransactionEnvelope|ContractEvent`, `--file` for file input). |
| `sdkt inspect <contract-id>` | Inspect a contract's ABI and storage (`--abi <wasm>` for ABI-aware decode). |
| `sdkt storage check <contract-id>` | Storage TTL / rent visibility (`--abi <wasm>`). |
| `sdkt storage analyze <contract-id>` | Classify Instance / Persistent / Temporary storage entries + TTL summary. |
| `sdkt storage estimate <wasm-path>` | Estimate storage cost for a WASM. |
| `sdkt storage read <contract-id> --key-xdr <BASE64_XDR>` | Read a contract storage entry by its complete LedgerKey. ABI optional for ScVal formatting. |
| `sdkt storage extend <contract-id> --ledgers <N>` | Extend TTL of known footprint keys (`ExtendFootprintTtl`). Instance key is always included; extra keys via `--key`. Does not restore archived entries. |
| `sdkt storage restore --contract <id> --envelope <xdr>` | Restore archived entries (`RestoreFootprint`) using the `restorePreamble` from simulating the failed invocation. `--dry-run` shows the keys and fee without submitting. |
| `sdkt tx inspect <hash>` | Transaction status / ledger inclusion. |
| `sdkt tx validate --envelope <xdr>` | Offline pre-flight validation of an envelope (parses + structural checks). |
| `sdkt tx decode <xdr>` | Human-readable view of an envelope (source, fee, operations with decoded args, footprint, signatures) for review before signing. Offline; `--format json` for a structured breakdown. |
| `sdkt tx simulate <xdr>` | Offline pre-flight via `simulateTransaction` (RPC). `--abi <wasm>` decodes the invoke result via the contract spec. |
| `sdkt tx sign --input <xdr> --identity <name>` | Sign an envelope with a local ED25519 identity — fully offline. |
| `sdkt tx submit <xdr>` | Submit a transaction (with optional poll; RPC). |
| `sdkt tx build` | Typed envelope builder. |
| `sdkt events <contract-id>` | Emitted-contract event explorer (`--abi <wasm>`; `--topic <SYMBOL>` filters by event name server-side). |
| `sdkt account <address>` | Account balances (native + trustlines) and complete typed signers (Horizon-enriched with RPC fallback). |
| `sdkt call <contract> <function> [--args TYPE:VALUE...]` | Read-only contract invocation. No signing, no submission. Returns result + events. `--abi <wasm>` decodes the result via the contract spec; `--abi-contract <id>` fetches the deployed contract's on-chain WASM instead. |
| `sdkt diff` | Offline comparison of WASM binaries and API surfaces. |
| `sdkt diff --old-wasm <A> --new-wasm <B>` | Offline ABI/function/event/type diff of two WASM files. Add `--upgrade-safety` for a breaking-change verdict. |
| `sdkt build` | Compile workspace rust contracts into optimized WASMs. |
| `sdkt-agent "<request>"` | Read-only natural-language front end: plans a request against the capability registry, refuses anything mutating, runs the CLI and returns structured evidence. `--format json` for a machine-readable result. Not on crates.io — build from source. See [docs/agent.md](docs/reference/agent.md). |
| `sdkt deploy --wasm <file> [--salt <salt>] [--arg <type:value>...]` | Upload WASM + instantiate. Salt is auto-generated if omitted (see [Deploy a single contract](#deploy-a-single-contract) below). Pass constructor arguments via repeated `--arg type:value` flags (uses `CreateContractV2`). Add `--deny-breaking --old-wasm <deployed.wasm>` to abort on a non-backwards-compatible upgrade. |
| `sdkt project deploy` | Deploy multi-contract workspace orchestrating topological dependency sorting. |
| `sdkt verify --contract <ID> [--wasm <file>] [--network <net>]` | Verify a deployed contract matches a local WASM (offline hash vs on-chain hash). |
| `sdkt health --contract <ID> [--wasm <file>] [--network <net>]` | Unified read-only contract posture report (WASM, storage, TTL, health verdict). |
| `sdkt wasm inspect <file>` | Inspect offline WASM metadata, sections, and specifications. |
| `sdkt wasm metadata --contract <contract>` | WASM metadata for a deployed contract (cached). |
| `sdkt wasm cache` | Manage the WASM cache (`info` / `remove` / `clear`). |
|| `sdkt audit <path.rs>` | Static security analysis (AUTH-001/002/003/004, MOVE-001). `--disable <RULE_ID>` to skip a rule. `--rules <path|id>` (repeatable) to load external rule paths or resolve installed plugin IDs. |
| `sdkt identity <generate\|import\|list\|show\|delete\|default>` | ED25519 keystore management. |
| `sdkt identity fund <name> --network-profile <NAME>` | Fund an identity via Stellar Testnet Friendbot. |
| `sdkt network <add\|list\|show\|remove>` | Named network profiles (RPC URL + passphrase). Combine with `--network-profile <NAME>` on any RPC command to avoid repeating endpoints; `--rpc-url` / `--network-passphrase` override. |
| `sdkt network diagnose [--network <testnet>]` | Read-only network identity / protocol / resource-limit diagnosis. Reports passphrase identity, protocol agreement, and ledger limits. Never signs or mutates. |
| `sdkt deployment-verify --contract <ID>` | Read-only deployment verification: is the deployed contract the artifact I built? Compares local WASM SHA-256 against on-chain executable. |
|| `sdkt init <name>` | Scaffold a new Soroban project (`--minimal`, `--force`). |
| `sdkt lock generate` | Write `sdkt.lock` recording each built artifact's SHA-256 + deploy order (after `sdkt build`). |
| `sdkt lock verify` | Verify `sdkt.lock` against current on-disk artifacts **and** package dependencies (lock matches manifest, git commits, path existence). Advisory; never fails the build. Prints `✓ lock file verified` / `✓ package dependencies verified` or lists drift. |
| `sdkt lock show` | Print the current `sdkt.lock` contents. |
| `sdkt package validate` | Validate the local package manifest (`[package]` metadata + local/git `[dependencies]` graph). Offline; never touches the network or a registry. |
| `sdkt package fetch [--force]` | Fetch declared dependencies into `.sdkt-cache` (local path passthrough; git clone/checkout). Never builds. `--force` updates existing checkouts. |
| `sdkt package update [--check] [--dry-run] [--format pretty\|json]` | Synchronize dependencies: refresh git deps to the latest available commit, rewrite `sdkt.lock`. `rev` stays pinned; `tag`/`branch` update on drift. `--check` reports only; `--dry-run` previews without touching cache/lock. |

### Deploy a single contract

`sdkt deploy` uploads a Soroban WASM to the network and instantiates it as a
new contract instance. It is the single-contract counterpart to
`sdkt project deploy` (which orchestrates multi-contract workspaces).

#### Deploy a contract to Testnet (step by step)

A fresh deploy requires a built WASM, a funded signing identity, and a salt.
Follow these steps in order:

```bash
# 1. Build your contract into a Soroban WASM
#    (from a project created with `sdkt init <name>`)
sdkt build

# 2. Generate a local ED25519 identity (used to sign the deploy transactions)
sdkt identity generate my-deployer

# 3. Configure the Testnet network profile
sdkt network add testnet \
  --rpc-url https://soroban-testnet.stellar.org \
  --passphrase "Test SDF Network ; September 2015" \
  --friendbot https://friendbot.stellar.org

# 4. Fund your identity on Testnet
#    Copy the public key from `sdkt identity show my-deployer` and paste it at:
#    https://friendbot.stellar.org
#    (Friendbot is a Testnet faucet — it does NOT work on Mainnet.)

# 5. Deploy (salt is auto-generated if omitted)
sdkt deploy \
  --wasm target/wasm32v1-none/release/<project>.wasm \
  --identity my-deployer \
  --network-profile testnet

# Or with explicit salt for deterministic address:
# openssl rand -hex 20
# sdkt deploy --wasm ... --salt <40-hex-chars> --identity my-deployer --network-profile testnet
```

Replace `<project>` with your crate name (the `name` field in `Cargo.toml`).
The `--wasm` path follows the Cargo convention
`target/<profile>/<crate>.wasm` — adjust if your build profile or target
directory differs.

#### Options
- `--wasm` (required): Path to a compiled Soroban WASM (32kb+ after `stellar contract build`).
- `--salt` (optional): 40-character hex string (20 bytes). Auto-generated if omitted. It salts the contract
  ID derivation so the same deployer + WASM + salt always yields the same contract
  address across networks. Provide explicitly for deterministic/reproducible deployment.
- `--identity <name>`: ED25519 identity from `sdkt identity` used to sign both
  transactions (upload + instantiate). Defaults to `default`.
- `--arg <type:value>`: Constructor argument in `type:value` format (e.g. `--arg u32:42`,
  `--arg string:hello`, `--arg bool:true`, `--arg bytes:0a0b`, `--arg address:G...`,
  `--arg symbol:init`). Pre-encoded base64 ScVal strings are also accepted as-is.
  Can be repeated for multiple constructor arguments. Contracts deployed with arguments use
  `CreateContractV2`.
- `--format <pretty|json>`: Output format (default `pretty`).
- `--deny-breaking`: Abort if the new WASM is not backwards-compatible with the
  currently deployed contract. Requires `--old-wasm`.
- `--old-wasm <file>`: Path to the existing on-chain baseline WASM. Used only
  with `--deny-breaking`.

#### Flow
1. Resolve the network (flag → profile → `.sdkt.toml` → built-in Testnet default).
2. Apply the mainnet-safety guard (mainnet requires explicit network selection).
3. Optionally run the `--deny-breaking` upgrade-safety check.
4. Load the signing identity and its key.
5. **Upload** — build an `UploadContractWasm` transaction, simulate, apply the
   returned `SorobanTransactionData` and authorization entries, sign, submit,
   and poll for confirmation.
6. **Instantiate** — build a `CreateContract` (or `CreateContractV2` when constructor
   arguments are provided via `--arg`) transaction with the WASM hash from
   the upload, the user-supplied salt, and any constructor arguments, simulate,
   finalize, sign, submit, and poll for confirmation.
7. Derive the contract ID from `Hash(networkId || HashIdPreimage::ContractId{...})`
   and report the deployment result.

#### Safety
- Mainnet deployments are refused unless the operator explicitly selects the
  network (via `--rpc-url` + `--network-passphrase`, or `--network-profile` whose
  passphrase is mainnet). Implicit Testnet defaults cannot touch mainnet.
- The salt must be exactly 40 hex characters; any other length or non-hex input
  is rejected before any network call.

#### Output
```
Deployment Result:
  WASM Hash: e71250b5...
  Contract ID: 0bde4658...
  Upload TX: c8599bb1...
  Create TX: 1e934b4e...
  Status: SUCCESS
```

### Multi-contract dependency graphs

A `.sdkt.toml` workspace declares contracts under `[contracts.<alias>]`. Each
contract may declare dependencies using either the canonical `depends_on`
or the legacy `deploy_after` field — both are merged during
resolution:

```toml
[contracts.token]
path = "contracts/token"

[contracts.router]
path = "contracts/router"
depends_on = ["token"]
```

`sdkt build`, `sdkt project deploy`, and `sdkt lock generate` all resolve the
same dependency graph via a single topological sort (Kahn's algorithm), so the
deploy order is deterministic and identical across commands. Invalid graphs are
rejected up front with a clear error:

- **Unknown dependency** — a `depends_on`/`deploy_after` entry that is not a
  defined `[contracts.*]`.
- **Self-dependency** — a contract that lists itself as a dependency.
- **Duplicate dependency** — the same dependency declared more than once
  (e.g. in both `depends_on` and `deploy_after`).
- **Circular dependency** — a cycle such as `a → b → a`.
- **Duplicate contract name** — two `[contracts.<alias>]` tables (TOML parse
  error, surfaced instead of silently defaulting to an empty config).

### Local package manifests

`sdkt package validate` lays the groundwork for a future package registry
**without** introducing any network or remote-registry functionality. It checks
a local package manifest declared in `.sdkt.toml`:

```toml
[package]
name = "my-token"
version = "0.1.0"
description = "Example Soroban token"

[dependencies.math]
path = "../math"

[dependencies.auth]
path = "./auth"
```

Validation rules (all offline — never performs network or registry I/O):

- `[package]` must have a `name` and a `version`.
- `version` must be a valid `MAJOR.MINOR.PATCH` shape (with optional
  pre-release/build metadata), matching the common semver form.
- Each `[dependencies.<name>]` entry is **exactly one source**: a local `path`
  **or** a `git` URL (never both). `deny_unknown_fields` rejects unrecognized
  keys so future source kinds (e.g. a registry) are explicit additions.
- For `git` deps, exactly one of `tag` / `branch` / `rev` must be set, and the
  URL must use `https`/`http`/`git`/`ssh` (or the `git@host:org/repo` SCP form).
- No self-dependency (a dependency key equal to the package `name`).
- For `path` deps, the referenced directory must exist.
- The dependency graph is checked for cycles (reusing the same topological-sort
  core as contract deploy-order resolution).

`sdkt package validate` exits non-zero on the first failure and prints a clear
message; with `--format json` it emits `{"valid": true}` or
`{"valid": false, "error": "..."}`.

### Fetching dependencies

`sdkt package fetch` materializes declared dependencies into a deterministic
local cache at `.sdkt-cache` (no registry, no authentication helpers, never
builds automatically):

```toml
[dependencies]
math = { path = "../math" }

token = { git = "https://github.com/org/token", tag = "v1.2.0" }
access = { git = "https://github.com/org/access", rev = "<commit>" }
utils = { git = "https://github.com/org/utils", branch = "main" }
```

- `path` deps are passed through (validated already by `validate`).
- `git` deps are cloned/checked out via the system `git` CLI into
  `.sdkt-cache/git/<stable-key>/`, then pinned to the requested `tag` /
  `branch` / `rev`. Re-running reuses an existing checkout unless `--force` is
  passed. A future registry source plugs into the same `DependencyFetcher`
  abstraction without touching callers.

The lock file (`sdkt.lock`) records each dependency's source, git URL,
requested reference, and resolved commit SHA (when available), so fetches are
reproducible. Local path deps remain unchanged in the lock.

### Network profiles

Save an RPC endpoint once and reference it from any RPC command instead of
repeating full URLs:

```bash
# Save a profile
sdkt network add testnet \
  --rpc-url https://soroban-testnet.stellar.org \
  --passphrase "Test SDF Network ; September 2015"

# Use it (any RPC command)
sdkt inspect <CONTRACT_ID> --network-profile testnet
sdkt account <ADDRESS> --network-profile testnet
```

Every RPC command (`inspect`, `verify`, `health`, `storage`, `events`, `account`,
`tx`, `fee`, `wasm`, `deploy`, `project deploy`) also accepts explicit
`--rpc-url <URL>` and `--network-passphrase <PASSPHRASE>` override flags.
**Precedence (highest wins):** explicit `--rpc-url` / `--network-passphrase` >
`--network-profile` > `.sdkt.toml` `[network]` > built-in testnet default.
Commands without these flags behave exactly as before. (`tx sign` is offline and
excluded.) See [docs/cli.md](docs/reference/cli.md) and [docs/examples.md](docs/getting-started/examples.md).

Most commands accept `--format json` for scripting / CI integration.

## Common Workflows

- **Audit every PR** — gate merges on `sdkt audit` via the
  [reusable Action](docs/compatibility/ci-cd.md), whose `severity-threshold`
  input fails the build on `critical` findings. The CLI itself reports findings
  but does **not** encode severity into its exit code — `sdkt audit` exits 0
  even when it prints critical findings, so gate on the Action (or parse
  `--format json`'s `summary.critical`) rather than on the bare exit code. See
  [docs/ci-cd.md](docs/compatibility/ci-cd.md).
- **Safe upgrades** — run `sdkt diff --upgrade-safety` in release CI to block
  breaking contract changes.
- **Local analysis** — `decode`, `diff`, and `audit` need no RPC; run them in
  CI or locally without secrets.

### End-to-end transaction signing (build → sign → submit)

`sdkt` can build, validate, simulate, **sign**, and submit a Soroban
transaction entirely from the CLI. Signing is **fully offline** — it uses a
local ED25519 identity from the keystore (`sdkt identity`); no RPC, no secret
ever leaves your machine.

```bash
# 1. Create a local signing identity (offline)
sdkt identity generate alice

# 2. Build an unsigned envelope (offline)
sdkt tx build \
  --source <SOURCE_ACCOUNT> \
  --sequence <SEQ> \
  --contract <CONTRACT_ID> \
  --function hello \
  --output unsigned.xdr

# 3. Validate the envelope offline and review what it does
sdkt tx validate --envelope unsigned.xdr
sdkt tx decode unsigned.xdr

# 4. Simulate against the network (RPC) to catch failures early
sdkt tx simulate --envelope unsigned.xdr

# 5. Sign with the local identity (offline) — picks testnet by default
sdkt tx sign --input unsigned.xdr --output signed.xdr --identity alice --network testnet

# 6. Submit the signed envelope (RPC)
sdkt tx submit --envelope signed.xdr
```

Notes:
- `tx sign` takes `--network testnet|mainnet|futurenet|custom:<passphrase>`; the
  network only affects the signature hash, so signing needs no RPC.
- `tx submit` / `tx simulate` read the network from `.sdkt.toml`
  (`[network]` section) or fall back to the default testnet RPC.
- `--output` is optional; without it, the signed base64 envelope is printed to
  stdout. Use `--format json` for scripting.

Copy-paste recipes for every subcommand are in
[docs/examples.md](docs/getting-started/examples.md).

## Upgrade Safety in CI

`sdkt` ships a reusable GitHub composite Action. See
[docs/ci-cd.md](docs/compatibility/ci-cd.md) for copy-paste workflows (audit-on-PR,
upgrade-safety-on-release).

## Documentation

- [docs/quick-start.md](docs/getting-started/quick-start.md) — five-minute first-time walkthrough (offline).
- [docs/agent.md](docs/reference/agent.md) — `sdkt-agent`: natural-language front end, capability surface, safety and refusal behaviour.
- [docs/testnet-walkthrough.md](docs/getting-started/testnet-walkthrough.md) — end-to-end Testnet loop: identity → fund → deploy → invoke → events / storage.
- [docs/getting-started.md](docs/getting-started/getting-started.md) — deeper offline `diff` and `audit` examples.
- [docs/examples.md](docs/getting-started/examples.md) — command recipes & CI gating.
- [docs/installation.md](docs/getting-started/installation.md) — build / install / features.
- [docs/compatibility.md](docs/compatibility/compatibility.md) — real-world contract compatibility matrix.
- [docs/ci-cd.md](docs/compatibility/ci-cd.md) — CI/CD with the reusable Action.
- [docs/adoption.md](docs/advanced/adoption.md) — ecosystem adoption and integration evidence.
- [SECURITY.md](SECURITY.md) — supported versions and vulnerability reporting.
- [CONTRIBUTING.md](CONTRIBUTING.md) — how to contribute.

Additional references: [docs/cli.md](docs/reference/cli.md) (full command reference),
[docs/faq.md](docs/getting-started/faq.md) (FAQ),
[docs/plugin-authoring.md](docs/plugins/plugin-authoring.md) (write your own audit
rules), and [ROADMAP.md](ROADMAP.md) · [CHANGELOG.md](CHANGELOG.md).

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md). All contributions are welcome — docs,
tests, and small fixes are great first PRs. Please follow the
[Code of Conduct](CODE_OF_CONDUCT.md).

## License

[MIT](LICENSE).