From ec51855500e61dcdfb66a69288423a54c5d48e08 Mon Sep 17 00:00:00 2001 From: Yana Matrosova Date: Wed, 10 Jun 2026 18:57:13 +0300 Subject: [PATCH] NYM-1199: fix @nymproject/types generation gap (export NodeAnnotation deps) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generated NodeAnnotationV1/V2.ts imported DetailedNodePerformanceV1/V2, DisplayRole, RoutingScore, ConfigScore and StressTestingScore, but those types (all of which derive ts_rs::TS with an export_to) were missing from tools/ts-rs-cli, so the files were never emitted — leaving dangling imports that broke `tsc` for the whole @nymproject/types package. Add the 6 types to ts-rs-cli (use + do_export!) and regenerate. The package now builds with 0 tsc errors, and the full nym-wallet Jest run goes from "84 pass + 4 suites unable to run" to 101 pass / 0 fail — recovering delegationIdentity and unbondedDelegation.acceptance. The 3 touched FamilyInvitation*/PastFamilyInvitation files are doc-comment syncs from the regeneration (the `at: number` overrides and enum variants are unchanged). Out of scope / still failing for a separate reason: api/nodeStatus.test.ts and api/networkOverview.test.ts reference the network value 'QA', which the Network enum (nym-wallet-types → SANDBOX | MAINNET) no longer includes — an app-code drift unrelated to families or type generation. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../changes/node-families-real-ipc/tasks.md | 2 +- tools/ts-rs-cli/src/main.rs | 18 +++++++++++++----- .../types/src/types/rust/ConfigScore.ts | 7 +++++++ .../types/rust/DetailedNodePerformanceV1.ts | 9 +++++++++ .../types/rust/DetailedNodePerformanceV2.ts | 12 ++++++++++++ .../types/src/types/rust/DisplayRole.ts | 3 +++ .../types/src/types/rust/FamilyInvitation.ts | 9 ++++++--- .../src/types/rust/FamilyInvitationStatus.ts | 6 ++++-- .../src/types/rust/PastFamilyInvitation.ts | 5 +++-- .../types/src/types/rust/RoutingScore.ts | 7 +++++++ .../types/src/types/rust/StressTestingScore.ts | 9 +++++++++ 11 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 ts-packages/types/src/types/rust/ConfigScore.ts create mode 100644 ts-packages/types/src/types/rust/DetailedNodePerformanceV1.ts create mode 100644 ts-packages/types/src/types/rust/DetailedNodePerformanceV2.ts create mode 100644 ts-packages/types/src/types/rust/DisplayRole.ts create mode 100644 ts-packages/types/src/types/rust/RoutingScore.ts create mode 100644 ts-packages/types/src/types/rust/StressTestingScore.ts diff --git a/nym-wallet/openspec/changes/node-families-real-ipc/tasks.md b/nym-wallet/openspec/changes/node-families-real-ipc/tasks.md index dd989e4d6f..bee5e2ea68 100644 --- a/nym-wallet/openspec/changes/node-families-real-ipc/tasks.md +++ b/nym-wallet/openspec/changes/node-families-real-ipc/tasks.md @@ -35,7 +35,7 @@ ## 6. Verify & docs -- [~] 6.1 **Families work is regression-free:** `cargo build` + `cargo clippy` clean; families code has no tsc errors; the contract-shape guard passes; families Jest suites green (43); full Jest run = **84 tests pass, 0 fail**. **Pre-existing, out-of-scope blocker:** 4 suites (`delegationIdentity`, `unbondedDelegation.acceptance`, `api/networkOverview`, `api/nodeStatus`) fail to *run* because the local `@nymproject/types` `dist` is stale and the package can't be rebuilt — its source has dangling imports to never-generated sibling types (`DetailedNodePerformanceV1`, `DisplayRole`) and a `Network`/`DelegationWithEverything` shape mismatch. None touch families; my uncommitted diff is entirely family-scoped (verified). Fixing the types-package generation gap is a separate change. Mock Tier-1 Playwright unaffected by the family type changes (mock path untouched). +- [~] 6.1 **Families work is regression-free; types-package generation gap fixed.** `cargo build` + `cargo clippy` clean; families code has no tsc errors; the contract-shape guard passes. Fixed the `@nymproject/types` build: `NodeAnnotationV1/V2` generated imports for `DetailedNodePerformanceV1/V2`, `DisplayRole`, `RoutingScore`, `ConfigScore`, `StressTestingScore` dangled because those (TS-deriving) types weren't in `tools/ts-rs-cli`; added them + regenerated → `tsc` builds the package with **0 errors**. Full wallet Jest now **101 pass, 0 fail** (was 84 + 4 suites unable to run); the two recovered suites are `delegationIdentity` + `unbondedDelegation.acceptance`. **Remaining (separate, out-of-scope, pre-existing):** `api/nodeStatus.test.ts` + `api/networkOverview.test.ts` fail to compile because `src/api/{nodeStatus,networkOverview}.ts` + their tests reference `'QA'`, which the source-of-truth `Network` enum (`nym-wallet-types`, → `SANDBOX | MAINNET`) doesn't include — an app-code drift unrelated to families or type generation; needs a product call (drop `QA` from the app code vs re-add it to `Network`). Mock Tier-1 Playwright unaffected (mock path untouched). - [x] 6.2 Confirmed against the deployed contract source: `ExecuteMsg::UpdateFamily { updated_name: Option, updated_description: Option }` (`node-families-contract/src/msg.rs`) — matches the `update_family` command + frontend `UpdateFamilyArgs` + parent §9.5. - [x] 6.3 Documented the real-IPC path in `e2e/README.md`: a "Real IPC layer (what the mock stands in for)" section (the 18 commands, the contract→wallet IPC-boundary translations, the mock→real provider switch) plus "Tier 3 — Sandbox real-IPC read smoke" and the guarded write-flow procedure (dedicated funded sandbox account, mnemonic via secret, target-only-self + cleanup). - [x] 6.4 Updated parent change `node-families-wallet` §9.4 to `[~]` "Realised by the `node-families-real-ipc` change" with a pointer to this change's Rust command layer + provider wiring. diff --git a/tools/ts-rs-cli/src/main.rs b/tools/ts-rs-cli/src/main.rs index 9389a49584..904292a478 100644 --- a/tools/ts-rs-cli/src/main.rs +++ b/tools/ts-rs-cli/src/main.rs @@ -1,11 +1,12 @@ #![allow(deprecated)] use nym_api_requests::models::{ - AnnotationResponseV1, AnnotationResponseV2, DeclaredRolesV1, DescribedNodeTypeV1, - GatewayCoreStatusResponse, HistoricalPerformanceResponse, HistoricalUptimeResponse, - MixnodeCoreStatusResponse, MixnodeStatus, MixnodeStatusResponse, NodeAnnotationV1, - NodeAnnotationV2, NodeDatePerformanceResponse, NodePerformanceResponse, - PerformanceHistoryResponse, StakeSaturationResponse, UptimeHistoryResponse, + AnnotationResponseV1, AnnotationResponseV2, ConfigScore, DeclaredRolesV1, DescribedNodeTypeV1, + DetailedNodePerformanceV1, DetailedNodePerformanceV2, DisplayRole, GatewayCoreStatusResponse, + HistoricalPerformanceResponse, HistoricalUptimeResponse, MixnodeCoreStatusResponse, + MixnodeStatus, MixnodeStatusResponse, NodeAnnotationV1, NodeAnnotationV2, + NodeDatePerformanceResponse, NodePerformanceResponse, PerformanceHistoryResponse, RoutingScore, + StakeSaturationResponse, StressTestingScore, UptimeHistoryResponse, }; use nym_api_requests::pagination::{PaginatedResponse, Pagination}; use nym_mixnet_contract_common::nym_node::{NodeConfigUpdate, Role}; @@ -182,6 +183,13 @@ fn main() -> anyhow::Result<()> { do_export!(AnnotationResponseV1); do_export!(NodeAnnotationV2); do_export!(AnnotationResponseV2); + // dependencies of NodeAnnotationV1/V2 (otherwise their generated imports dangle) + do_export!(DisplayRole); + do_export!(DetailedNodePerformanceV1); + do_export!(DetailedNodePerformanceV2); + do_export!(RoutingScore); + do_export!(ConfigScore); + do_export!(StressTestingScore); do_export!(NodePerformanceResponse); do_export!(NodeDatePerformanceResponse); do_export!(PerformanceHistoryResponse); diff --git a/ts-packages/types/src/types/rust/ConfigScore.ts b/ts-packages/types/src/types/rust/ConfigScore.ts new file mode 100644 index 0000000000..82930c798b --- /dev/null +++ b/ts-packages/types/src/types/rust/ConfigScore.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ConfigScore = { +/** + * Total score after taking all the criteria into consideration + */ +score: number, versions_behind: number | null, self_described_api_available: boolean, accepted_terms_and_conditions: boolean, runs_nym_node_binary: boolean, }; diff --git a/ts-packages/types/src/types/rust/DetailedNodePerformanceV1.ts b/ts-packages/types/src/types/rust/DetailedNodePerformanceV1.ts new file mode 100644 index 0000000000..8e0a744867 --- /dev/null +++ b/ts-packages/types/src/types/rust/DetailedNodePerformanceV1.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ConfigScore } from "./ConfigScore"; +import type { RoutingScore } from "./RoutingScore"; + +export type DetailedNodePerformanceV1 = { +/** + * routing_score * config_score + */ +performance_score: number, routing_score: RoutingScore, config_score: ConfigScore, }; diff --git a/ts-packages/types/src/types/rust/DetailedNodePerformanceV2.ts b/ts-packages/types/src/types/rust/DetailedNodePerformanceV2.ts new file mode 100644 index 0000000000..9a7e23a46f --- /dev/null +++ b/ts-packages/types/src/types/rust/DetailedNodePerformanceV2.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ConfigScore } from "./ConfigScore"; +import type { RoutingScore } from "./RoutingScore"; +import type { StressTestingScore } from "./StressTestingScore"; + +export type DetailedNodePerformanceV2 = { +/** + * routing_score * config_score + * or + * routing_score * config_score * stress_testing_score, if enabled + */ +performance_score: number, routing_score: RoutingScore, config_score: ConfigScore, stress_testing_score: StressTestingScore, }; diff --git a/ts-packages/types/src/types/rust/DisplayRole.ts b/ts-packages/types/src/types/rust/DisplayRole.ts new file mode 100644 index 0000000000..621f5ce685 --- /dev/null +++ b/ts-packages/types/src/types/rust/DisplayRole.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type DisplayRole = "entryGateway" | "layer1" | "layer2" | "layer3" | "exitGateway" | "standby"; diff --git a/ts-packages/types/src/types/rust/FamilyInvitation.ts b/ts-packages/types/src/types/rust/FamilyInvitation.ts index 43ddd8ffcb..89c8bf806d 100644 --- a/ts-packages/types/src/types/rust/FamilyInvitation.ts +++ b/ts-packages/types/src/types/rust/FamilyInvitation.ts @@ -3,9 +3,12 @@ /** * A pending invitation for a node to join a particular family. * - * Invitations are stored until they are accepted, rejected, revoked, or until the - * chain advances past `expires_at` (in which case they remain in storage but are - * treated as inert — there is no background process clearing expired invitations). + * Invitations are stored until they are accepted, rejected, or revoked. Once the + * chain advances past `expires_at` an invitation becomes inert but stays in storage + * — there is no background process clearing expired invitations. A timed-out + * invitation is cleared either when explicitly revoked/rejected, or when the family + * issues a fresh invitation for the same node, which archives the stale one as + * `Expired` and supersedes it. */ export type FamilyInvitation = { /** diff --git a/ts-packages/types/src/types/rust/FamilyInvitationStatus.ts b/ts-packages/types/src/types/rust/FamilyInvitationStatus.ts index 06fb7701d9..50825250c2 100644 --- a/ts-packages/types/src/types/rust/FamilyInvitationStatus.ts +++ b/ts-packages/types/src/types/rust/FamilyInvitationStatus.ts @@ -3,7 +3,9 @@ /** * Terminal status for an invitation that has been moved out of the pending set. * - * Note: timed-out invitations are not represented here — they are simply left in - * the pending set (see `FamilyInvitation::expires_at`). + * Note: an invitation that merely times out is **not** archived here on its own — + * it is left inert in the pending set (see `FamilyInvitation::expires_at`). It only + * reaches `Expired` if the family issues a fresh invitation for the same node, which + * supersedes and archives the stale one. */ export type FamilyInvitationStatus = { "pending": { at: number, } } | { "accepted": { at: number, } } | { "rejected": { at: number, } } | { "revoked": { at: number, } }; diff --git a/ts-packages/types/src/types/rust/PastFamilyInvitation.ts b/ts-packages/types/src/types/rust/PastFamilyInvitation.ts index d8c8707dd7..e7b7026fe6 100644 --- a/ts-packages/types/src/types/rust/PastFamilyInvitation.ts +++ b/ts-packages/types/src/types/rust/PastFamilyInvitation.ts @@ -4,8 +4,9 @@ import type { FamilyInvitationStatus } from "./FamilyInvitationStatus"; /** * Historical record of an invitation that has reached a terminal state - * (`Accepted`, `Rejected`, or `Revoked`). Timed-out invitations are **not** - * archived here — they remain in the pending map until explicitly cleared. + * (`Accepted`, `Rejected`, `Revoked`, or `Expired`). A timed-out invitation is + * archived here only when a fresh invitation for the same node supersedes it + * (status `Expired`); otherwise it stays in the pending map until explicitly cleared. */ export type PastFamilyInvitation = { /** diff --git a/ts-packages/types/src/types/rust/RoutingScore.ts b/ts-packages/types/src/types/rust/RoutingScore.ts new file mode 100644 index 0000000000..f00098ef60 --- /dev/null +++ b/ts-packages/types/src/types/rust/RoutingScore.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RoutingScore = { +/** + * Total score after taking all the criteria into consideration + */ +score: number, }; diff --git a/ts-packages/types/src/types/rust/StressTestingScore.ts b/ts-packages/types/src/types/rust/StressTestingScore.ts new file mode 100644 index 0000000000..503a2cdd6e --- /dev/null +++ b/ts-packages/types/src/types/rust/StressTestingScore.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type StressTestingScore = { score: number, +/** + * Distinguishes a genuine zero score (node was tested and scored 0) from + * "node was unreachable" (no successful sample was collected). Consumers may use + * this to decide whether to penalise the node or treat the score as missing. + */ +was_reachable: boolean, };