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
12 changes: 0 additions & 12 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,6 @@ on:
workflow_dispatch:

jobs:
cargo-audit:
name: Cargo Audit
runs-on: ubuntu-latest
permissions:
checks: write
contents: read
steps:
- uses: actions/checkout@v6
- uses: rustsec/audit-check@v2.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}

cargo-deny:
name: Cargo Deny
runs-on: ubuntu-latest
Expand Down
61 changes: 61 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,67 @@ follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.9.0] - 2026-10-08

### Changed — breaking

- The five `canton-lib` crates, and `cbtc-tui`'s two, move from
`tag = "v0.9.0"` to `tag = "v0.11.0"`. Canton 3.6.1 rejects the top-level
`filter` and `verbose` fields of an active-contracts request with
`DEPRECATED_API_DISABLED`. `canton-lib` 0.9.0 sends both. 0.10.0 sends
`eventFormat` in their place.

The effect of that rejection depends on the path the query takes:

- `canton-lib` sends some queries over a websocket, such as
`cbtc::active_contracts::get` and the `cbtc-tui` balance query. In
`canton-lib` 0.9.0, those functions read the rejection as a stream with no
contracts. So on a 3.6.1 participant they returned an empty result and no
error. On devnet, `check_balance` reported 0 for a party that held 4
holdings.
- Mint and redeem call the HTTP function
`ledger::active_contracts::get_by_party`. It already returned
`Err("post_v2_state_active_contracts failed: ...")`, so mint and redeem
failed with that error.

`canton-lib` 0.10.1 fixes the websocket functions. A query that the Ledger
API rejects there now returns
`Err("Ledger API returned <code>: <cause>")`. The HTTP path keeps its
`post_v2_state_active_contracts failed` text.

This release is tested on Canton 3.6.1 only, on devnet. The participant's
error says that Canton deprecated the old fields in 3.4. That suggests
`eventFormat` works from Canton 3.4, but nobody has tested an older
participant.

All seven pins move together, because mixing two tags across the manifests
builds two `common` packages. The check is that `Cargo.lock` holds one
`name = "common"` entry.

- `canton-api-client` moves from 3.6.0-0.1.0 to 3.6.1-0.1.0 in both
manifests. `canton-lib` 0.11.0 uses client 3.6.1, and `ledger` re-exports
the client's `models`. With two client versions, the `ledger::models` types
and this crate's own client types differ.

Client 3.6.1 adds the `CanActAsAnyParty` user right as `Kind::KindOneOf1`.
The generator numbers the variants in order, so `CanReadAs` moves from
`KindOneOf3` to `KindOneOf4`. `cbtc-tui`'s `parse_party_rights` matches the
new variant.

This release is breaking because of these pins. `cbtc` re-exports `common`
types such as `DamlDecimal`, and `common` moves from 0.9.0 to 0.11.0. Its
public functions also take and return `ledger::models` types. A consumer
that also pins `canton-lib` must move that pin to `v0.11.0`. A consumer
that depends on `canton-api-client` must move it to 3.6.1-0.1.0.
Under SemVer's 0.x rules the next version is 0.9.0, not 0.8.1.

### Security

- `Cargo.lock` moves `h2` from 0.4.12 to 0.4.19. Version 0.4.12 carries
RUSTSEC-2026-0258, which Cargo Deny reports. The lockfile sets the version
for `cbtc-tui` and the examples. A consumer's own lockfile sets it for the
consumer.

## [0.8.0] - 2026-10-01

### Added
Expand Down
30 changes: 15 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
[package]
name = "cbtc"
version = "0.8.0"
version = "0.9.0"
edition = "2024"
autoexamples = false

[lints.clippy]
uninlined_format_args = "allow"

[dependencies]
token = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.9.0" }
ledger = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.9.0" }
keycloak = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.9.0" }
common = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.9.0" }
registry = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.9.0" }
token = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.11.0" }
ledger = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.11.0" }
keycloak = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.11.0" }
common = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.11.0" }
registry = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.11.0" }
tokio = { version = "1.48.0", features = ["macros", "rt-multi-thread"] }
serde_json = "1"
chrono = "0.4.42"
uuid = { version = "1.18", features = ["v4"] }
csv = "1.3"
serde = { version = "1.0", features = ["derive"] }
dotenvy = "0.15"
canton-api-client = "3.6.0-0.1.0"
canton-api-client = "3.6.1-0.1.0"
reqwest = { version = "0.12.24", features = ["json"] }

[dev-dependencies]
Expand Down
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ Add to your `Cargo.toml`:
# needs no canton-lib dependency for the Token Standard types. If you add
# one, pin the same revision: a different pin makes Cargo build two `common`
# packages, and then cbtc::DamlDecimal and common::decimal::DamlDecimal differ.
cbtc = { git = "ssh://git@github.com/DLC-link/cbtc-lib", tag = "v0.8.0" }
keycloak = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.9.0" }
cbtc = { git = "ssh://git@github.com/DLC-link/cbtc-lib", tag = "v0.9.0" }
keycloak = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.11.0" }
```

`cbtc` v0.8.0 pins `canton-lib` at `v0.9.0`, so the `keycloak` pin above names
`cbtc` v0.9.0 pins `canton-lib` at `v0.11.0`, so the `keycloak` pin above names
that same tag. Pinning a different tag or a revision here builds two `common`
packages.

Expand Down Expand Up @@ -203,10 +203,10 @@ Add this to your `Cargo.toml`:

```toml
[dependencies]
cbtc = { git = "ssh://git@github.com/DLC-link/cbtc-lib", tag = "v0.8.0" }
cbtc = { git = "ssh://git@github.com/DLC-link/cbtc-lib", tag = "v0.9.0" }
```

`cbtc-lib` is released as `v0.8.0`.
`cbtc-lib` is released as `v0.9.0`.

Or for local development:

Expand Down Expand Up @@ -632,9 +632,9 @@ curl -X POST $LEDGER_HOST/v2/state/active-contracts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"filter": {
"eventFormat": {
"filtersByParty": {
"$SENDER_PARTY_ID": {
"'$SENDER_PARTY_ID'": {
"cumulative": [{
"identifierFilter": {
"InterfaceFilter": {
Expand All @@ -647,9 +647,9 @@ curl -X POST $LEDGER_HOST/v2/state/active-contracts \
}
}]
}
}
},
"verbose": false
},
"verbose": false,
"activeAtOffset": '$(echo $LEDGER_OFFSET | jq -R 'tonumber')'
}' | jq
```
Expand Down
6 changes: 3 additions & 3 deletions cbtc-tui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ edition = "2024"

[dependencies]
anyhow = "1"
canton-api-client = "3.6.0-0.1.0"
canton-api-client = "3.6.1-0.1.0"
cbtc = { path = ".." }
chrono = "0.4"
clap = { version = "4", features = ["derive", "env"] }
dirs = "5"
keycloak = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.9.0" }
ledger = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.9.0" }
keycloak = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.11.0" }
ledger = { git = "ssh://git@github.com/DLC-link/canton-lib", tag = "v0.11.0" }
ratatui = "0.29"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand Down
2 changes: 1 addition & 1 deletion cbtc-tui/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn parse_party_rights(resp: &ListUserRightsResponse) -> Vec<PartyRight> {
};
let (party, act, read) = match kind {
Kind::KindOneOf(k) => (k.can_act_as.value.party.clone(), true, false),
Kind::KindOneOf3(k) => (k.can_read_as.value.party.clone(), false, true),
Kind::KindOneOf4(k) => (k.can_read_as.value.party.clone(), false, true),
_ => continue,
};
let entry = by_party.entry(party.clone()).or_insert(PartyRight {
Expand Down
Loading