Skip to content

Conversation

@shumkov
Copy link
Collaborator

@shumkov shumkov commented Dec 1, 2025

Issue being fixed or feature implemented

Hardcoded list of evonodes is outdated. Since we already pre-fetch trusted list of quorums we can do same with evo nodes.

What was done?

  • Pre-fetch mainnet or testnet addresses together with quorums

How Has This Been Tested?

With existing tests

Breaking Changes

None

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

Summary by CodeRabbit

  • New Features

    • Dynamic masternode address discovery with validation.
    • Discovered addresses are cached and used to speed SDK initialization.
  • API Changes

    • DPNS proof methods now return a unified proof metadata response type, replacing previous specific proof response shapes.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

Walkthrough

Adds masternode discovery to the trusted provider, a Wasm adapter that converts and returns discovered addresses, caching of discovered mainnet/testnet addresses during prefetch for WasmSdk builders, and consolidation of DPNS proof responses into a single ProofMetadataResponseWasm type.

Changes

Cohort / File(s) Summary
Context Provider: discovery API
packages/rs-sdk-trusted-context-provider/src/provider.rs
Adds MasternodeEntry and MasternodeDiscoveryResponse (Deserialize) and new pub async fn fetch_masternode_addresses(&self) -> Result<Vec<Url>, TrustedContextProviderError> which requests /masternodes, filters enabled/version_check-success entries, builds DAPI HTTPS URLs (network-aware port), and returns validated URLs or an error.
Wasm SDK: trusted context adapter
packages/wasm-sdk/src/context_provider.rs
Adds pub async fn fetch_masternode_addresses() on WasmTrustedContext that calls the inner provider, converts Url -> Uri -> Address, collects into an AddressList, and maps errors to ContextProviderError::Generic.
Wasm SDK: caching & builders
packages/wasm-sdk/src/sdk.rs
Introduces MAINNET_DISCOVERED_ADDRESSES and TESTNET_DISCOVERED_ADDRESSES (Lazy<Mutex<Option<Vec<Address>>>>), parse_addresses, default address helpers, fetch_and_cache_addresses helper, populates caches during prefetch_trusted_quorums_* flows, and updates WasmSdkBuilder::new_mainnet / new_testnet to read from caches (fallback to defaults if not prefetched).
Wasm SDK: DPNS proof API consolidation
packages/wasm-sdk/src/dpns.rs
Removes DpnsUsernamesProofResponseWasm and DpnsUsernameProofResponseWasm; changes proof-returning functions to return ProofMetadataResponseWasm, updates wasm_bindgen unchecked_return_type annotations, and constructs responses via ProofMetadataResponseWasm::from_parts + set_data.
Imports & misc
packages/wasm-sdk/src/*.rs, packages/rs-sdk-trusted-context-provider/src/*.rs
Adds imports for serde::Deserialize, Url, Uri, Address types where needed and adjusts imports to support the new discovery + conversion logic.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant WasmSDK as Wasm SDK / Builder
participant Prefetch as Prefetch Flow
participant WasmCtx as WasmTrustedContext
participant Provider as TrustedHttpContextProvider
participant Cache as MAINNET/TESTNET Cache

WasmSDK->>Prefetch: start prefetch_trusted_quorums_*()
Prefetch->>WasmCtx: call fetch_masternode_addresses()
WasmCtx->>Provider: provider.fetch_masternode_addresses()
Provider->>Provider: HTTP GET /masternodes; parse JSON; filter entries
Provider-->>WasmCtx: Vec<Url> (validated)
WasmCtx-->>Prefetch: AddressList (converted)
Prefetch->>Cache: store addresses in static cache
Note right of Cache: Builders read these caches later
WasmSDK->>Cache: WasmSdkBuilder::new_* reads cached addresses
alt cache empty
    Cache-->>WasmSDK: fallback to default addresses
else cache populated
    Cache-->>WasmSDK: addresses used to initialize builder
end

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Inspect HTTP request, JSON deserialization, filtering and port/host extraction in provider.rs.
  • Validate URL -> Uri -> Address conversions and error mapping in context_provider.rs.
  • Review synchronization and error handling of Lazy<Mutex<Option<Vec<Address>>>> in sdk.rs.
  • Confirm wasm_bindgen unchecked_return_type changes and ProofMetadataResponseWasm construction in dpns.rs.

Poem

🐇
I sniffed the nodes beneath the net,
Collected hops where dap‑is set.
I cached a trail of shining hops,
One proof to bind the naming props.
Now builders leap — hop, hop, repeat.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(sdk): pre-fetch trusted address list' accurately summarizes the main change: adding functionality to pre-fetch trusted masternode/evonode addresses for the SDK, replacing outdated hardcoded lists.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/sdk/fetch-masternodes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
packages/wasm-sdk/src/sdk.rs (3)

22-36: Consider propagating mutex errors instead of panicking.

Line 34 uses .unwrap() on mutex lock, which will panic if the mutex is poisoned. While mutex poisoning is rare, panics in WASM can be difficult to debug. Consider using .lock().map_err(...) to convert to a WasmSdkError for consistency with other error handling in this module.

-    *cache.lock().unwrap() = Some(addresses);
+    *cache
+        .lock()
+        .map_err(|e| WasmSdkError::generic(format!("Failed to acquire address cache lock: {}", e)))?
+        = Some(addresses);

234-246: Consider returning Result for consistency and better error handling.

new_mainnet() uses .expect() which will panic if prefetchTrustedQuorumsMainnet() wasn't called first. Panics in WASM are difficult to debug and crash the entire application. The trusted variant (new_mainnet_trusted) properly returns Result<Self, WasmSdkError>.

Consider changing the signature to pub fn new_mainnet() -> Result<Self, WasmSdkError> for consistency and to provide users with actionable error messages instead of panics.

     #[wasm_bindgen(js_name = "mainnet")]
-    pub fn new_mainnet() -> Self {
-        let mainnet_addresses = MAINNET_DISCOVERED_ADDRESSES.lock().unwrap().clone().expect(
-            "Mainnet addresses not prefetched. Call prefetchTrustedQuorumsMainnet() first.",
-        );
+    pub fn new_mainnet() -> Result<Self, WasmSdkError> {
+        let mainnet_addresses = MAINNET_DISCOVERED_ADDRESSES
+            .lock()
+            .map_err(|e| WasmSdkError::generic(format!("Failed to acquire address cache lock: {}", e)))?
+            .clone()
+            .ok_or_else(|| {
+                WasmSdkError::generic(
+                    "Mainnet addresses not prefetched. Call prefetchTrustedQuorumsMainnet() first.",
+                )
+            })?;
 
         let address_list = dash_sdk::sdk::AddressList::from_iter(mainnet_addresses);
         let sdk_builder = SdkBuilder::new(address_list)
             .with_network(dash_sdk::dpp::dashcore::Network::Dash)
             .with_context_provider(WasmContext {});
 
-        Self(sdk_builder)
+        Ok(Self(sdk_builder))
     }

281-293: Same issue: consider returning Result for consistency.

Apply the same refactor as suggested for new_mainnet() to avoid panics in WASM.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc2dd30 and 60c7aa6.

📒 Files selected for processing (3)
  • packages/wasm-sdk/src/context_provider.rs (1 hunks)
  • packages/wasm-sdk/src/dpns.rs (3 hunks)
  • packages/wasm-sdk/src/sdk.rs (8 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Rust code must pass cargo clippy --workspace linter checks
Rust code must be formatted using cargo fmt --all

**/*.rs: Use 4-space indent for Rust files
Follow rustfmt defaults and keep code clippy-clean for Rust modules
Use snake_case for Rust module names
Use PascalCase for Rust type names
Use SCREAMING_SNAKE_CASE for Rust constants

Files:

  • packages/wasm-sdk/src/context_provider.rs
  • packages/wasm-sdk/src/sdk.rs
  • packages/wasm-sdk/src/dpns.rs
🧠 Learnings (15)
📓 Common learnings
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2690
File: packages/wasm-sdk/src/queries/document.rs:383-384
Timestamp: 2025-07-10T00:37:09.586Z
Learning: In the Dash platform, DPNS (Dash Platform Name Service) contracts have the same ID across all networks (mainnet, testnet, etc.), so hardcoding the DPNS contract ID is appropriate and doesn't need to be configurable.
Learnt from: shumkov
Repo: dashpay/platform PR: 2206
File: packages/rs-platform-version/src/version/protocol_version.rs:155-157
Timestamp: 2024-10-09T00:22:57.778Z
Learning: In the dashmate default configurations, the default protocol version for local networks has been removed, and an update mechanism for the protocol version in the consensus parameters has been implemented.
Learnt from: shumkov
Repo: dashpay/platform PR: 2206
File: packages/rs-platform-version/src/version/protocol_version.rs:155-157
Timestamp: 2024-10-04T09:08:48.470Z
Learning: In the dashmate default configurations, the default protocol version for local networks has been removed, and an update mechanism for the protocol version in the consensus parameters has been implemented.
📚 Learning: 2024-11-28T13:49:17.301Z
Learnt from: shumkov
Repo: dashpay/platform PR: 2317
File: packages/rs-dapi-client/src/address_list.rs:175-180
Timestamp: 2024-11-28T13:49:17.301Z
Learning: In Rust code in `packages/rs-dapi-client/src/address_list.rs`, do not change the interface of deprecated methods like `add_uri`, even to fix potential panics.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
  • packages/wasm-sdk/src/dpns.rs
📚 Learning: 2024-10-10T10:30:19.883Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2232
File: packages/rs-sdk/src/mock/sdk.rs:90-95
Timestamp: 2024-10-10T10:30:19.883Z
Learning: In `packages/rs-sdk/src/mock/sdk.rs`, the `load_expectations` method in `MockDashPlatformSdk` remains asynchronous (`async`) for backward compatibility, even though it now delegates to the synchronous `load_expectations_sync` method.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
📚 Learning: 2024-10-18T15:39:51.172Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2254
File: packages/rs-sdk/src/sdk.rs:585-585
Timestamp: 2024-10-18T15:39:51.172Z
Learning: The 'platform' project uses Rust version 1.80, so code in 'packages/rs-sdk' can use features available in Rust 1.80, such as the `abs_diff()` method.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
📚 Learning: 2024-12-05T12:59:22.044Z
Learnt from: lklimek
Repo: dashpay/platform PR: 1924
File: packages/rs-dapi-client/src/request_settings.rs:74-74
Timestamp: 2024-12-05T12:59:22.044Z
Learning: The `AppliedRequestSettings` struct in `packages/rs-dapi-client/src/request_settings.rs` is intended for internal use within the monorepo and is not part of the public API.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
📚 Learning: 2024-10-30T11:19:59.163Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2277
File: packages/rs-sdk/tests/fetch/config.rs:233-233
Timestamp: 2024-10-30T11:19:59.163Z
Learning: In the Rust SDK's `rs-sdk/tests` integration tests (e.g., in `packages/rs-sdk/tests/fetch/config.rs`), we cannot create objects during tests because there is no support for object creation in this context. Therefore, hardcoded values for test identities must be used.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
📚 Learning: 2025-11-25T13:10:23.481Z
Learnt from: CR
Repo: dashpay/platform PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T13:10:23.481Z
Learning: Use WASM bindings to connect Rust and JavaScript code

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
  • packages/wasm-sdk/src/dpns.rs
📚 Learning: 2024-10-28T10:38:49.538Z
Learnt from: shumkov
Repo: dashpay/platform PR: 2259
File: packages/rs-dapi-client/src/executor.rs:49-56
Timestamp: 2024-10-28T10:38:49.538Z
Learning: In `packages/rs-dapi-client/src/executor.rs`, the `ExecutionResponse` struct always has a non-optional `address` field of type `Address` because an address is always present when there's a successful response.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
📚 Learning: 2025-10-23T13:04:39.160Z
Learnt from: thephez
Repo: dashpay/platform PR: 2816
File: packages/js-dapi-client/lib/networkConfigs.js:17-40
Timestamp: 2025-10-23T13:04:39.160Z
Learning: For the testnet DAPI address whitelist in packages/js-dapi-client/lib/networkConfigs.js, nodes may be intentionally excluded even if they are ENABLED if they are running pre-2.1 versions. Version compatibility is an important filtering criterion beyond just enabled status.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
📚 Learning: 2025-08-05T13:55:39.147Z
Learnt from: thephez
Repo: dashpay/platform PR: 2718
File: packages/wasm-sdk/index.html:0-0
Timestamp: 2025-08-05T13:55:39.147Z
Learning: The get_identity_keys_with_proof_info function in the Rust WASM bindings does not support the "search" key request type and lacks the searchPurposeMap parameter. When proof mode is enabled with keyRequestType === 'search', the implementation falls back to the non-proof version (get_identity_keys) to maintain functionality.

Applied to files:

  • packages/wasm-sdk/src/dpns.rs
📚 Learning: 2025-09-03T14:42:29.958Z
Learnt from: thephez
Repo: dashpay/platform PR: 2754
File: packages/wasm-sdk/docs.html:1970-1971
Timestamp: 2025-09-03T14:42:29.958Z
Learning: In packages/wasm-sdk/, the docs.html file is auto-generated from api-definitions.json. Any documentation fixes should be made in api-definitions.json rather than directly in docs.html, as manual changes to docs.html would be overwritten during regeneration.

Applied to files:

  • packages/wasm-sdk/src/dpns.rs
📚 Learning: 2025-09-03T14:41:16.196Z
Learnt from: thephez
Repo: dashpay/platform PR: 2754
File: packages/wasm-sdk/AI_REFERENCE.md:766-766
Timestamp: 2025-09-03T14:41:16.196Z
Learning: In packages/wasm-sdk/, the AI_REFERENCE.md file is auto-generated from api-definitions.json. Any documentation fixes should be made in api-definitions.json rather than directly in AI_REFERENCE.md, as manual changes to AI_REFERENCE.md would be overwritten during regeneration.

Applied to files:

  • packages/wasm-sdk/src/dpns.rs
📚 Learning: 2025-07-28T20:00:08.502Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2711
File: packages/wasm-sdk/AI_REFERENCE.md:771-783
Timestamp: 2025-07-28T20:00:08.502Z
Learning: In packages/wasm-sdk/AI_REFERENCE.md, the documentation correctly shows the actual SDK method signatures (including identityCreate and identityTopUp with their full parameter lists), which may differ from the UI inputs shown in fixed_definitions.json. The UI may collect fewer parameters from users while handling additional requirements internally.

Applied to files:

  • packages/wasm-sdk/src/dpns.rs
📚 Learning: 2025-02-10T11:26:36.709Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2405
File: packages/wasm-sdk/src/verify.rs:26-68
Timestamp: 2025-02-10T11:26:36.709Z
Learning: In the wasm-sdk package, empty vectors and placeholder values are intentionally used in verification functions during the proof-of-concept stage to ensure proper compilation and type checking.

Applied to files:

  • packages/wasm-sdk/src/dpns.rs
📚 Learning: 2025-09-03T19:33:21.688Z
Learnt from: thephez
Repo: dashpay/platform PR: 2754
File: packages/wasm-sdk/api-definitions.json:1285-1285
Timestamp: 2025-09-03T19:33:21.688Z
Learning: In packages/wasm-sdk/api-definitions.json, thephez prefers to keep the existing "ripemd160hash20bytes1234" placeholder for ECDSA_HASH160 data field in documentation examples rather than using a valid base64-encoded format, maintaining consistency with the previous documentation approach.

Applied to files:

  • packages/wasm-sdk/src/dpns.rs
🧬 Code graph analysis (3)
packages/wasm-sdk/src/context_provider.rs (2)
packages/rs-sdk/src/sdk.rs (1)
  • new (867-872)
packages/rs-dapi-client/src/address_list.rs (3)
  • uri (65-67)
  • try_from (52-60)
  • from_iter (274-281)
packages/wasm-sdk/src/sdk.rs (2)
packages/rs-dapi-client/src/dapi_client.rs (1)
  • address_list (121-123)
packages/wasm-sdk/src/error.rs (1)
  • generic (69-71)
packages/wasm-sdk/src/dpns.rs (1)
packages/wasm-sdk/src/queries/mod.rs (5)
  • metadata (242-244)
  • proof (252-254)
  • from_parts (263-273)
  • from (89-98)
  • from (195-204)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Rust packages (wasm-sdk) / Tests
  • GitHub Check: Rust packages (wasm-sdk) / Unused dependencies
  • GitHub Check: Rust packages (wasm-sdk) / Linting
  • GitHub Check: Build Docker images (RS-DAPI, rs-dapi, rs-dapi) / Build RS-DAPI image
  • GitHub Check: Build Docker images (Drive, drive, drive-abci) / Build Drive image
  • GitHub Check: Build JS packages / Build JS
  • GitHub Check: Rust crates security audit
🔇 Additional comments (8)
packages/wasm-sdk/src/context_provider.rs (1)

137-158: LGTM! Clean implementation of masternode address fetching.

The method correctly:

  • Fetches URLs from the inner provider
  • Parses each URL to a Uri using from_maybe_shared
  • Converts each Uri to an Address via TryFrom
  • Collects addresses into an AddressList using from_iter

Error messages are descriptive and include the problematic URL for debugging.

packages/wasm-sdk/src/sdk.rs (3)

17-20: LGTM! Static caches for discovered addresses.

The lazy-initialized mutex-protected caches are appropriate for storing prefetched masternode addresses that can be shared across SDK builder invocations.


86-104: LGTM! Address fetching integrated into prefetch flow.

The integration is well-placed: addresses are fetched after quorum prefetch succeeds, and before storing the context. If address fetching fails, the entire prefetch operation fails cleanly, allowing the user to retry.


263-271: LGTM! Proper error handling for missing prefetched addresses.

Using ok_or_else with a descriptive error message is the right approach. The error clearly instructs users to call the prefetch method first.

packages/wasm-sdk/src/dpns.rs (4)

3-3: LGTM! Simplified imports for unified response type.

The import cleanup removes the now-unused DPNS-specific response types in favor of the unified ProofMetadataResponseWasm.


167-184: LGTM! Clean migration to unified response type.

The method now returns ProofMetadataResponseWasm using from_parts(), correctly passing the usernames array as a JsValue and converting metadata/proof to their WASM wrapper types.


462-473: LGTM! Proper TypeScript typing for the unified response.

The unchecked_return_type attribute correctly specifies ProofMetadataResponseTyped<Array<string>> which matches the data payload being returned.


475-501: LGTM! Correctly extracts single username from array response.

The implementation cleverly reuses fetch_dpns_usernames_with_proof, then modifies the response data to return just the first username (or null). The unchecked_return_type = "ProofMetadataResponseTyped<string | null>" accurately reflects the return type. The set_data method is available on ProofMetadataResponseWasm and properly handles the type conversion.

@shumkov shumkov moved this to In review / testing in Platform team Dec 1, 2025
@shumkov shumkov self-assigned this Dec 1, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/rs-sdk-trusted-context-provider/src/provider.rs (1)

246-308: Discovery logic is solid; consider hardening host parsing and JSON decoding

The overall flow (call /masternodes, enforce HTTP success + success == true, filter for ENABLED + version_check == "success", and construct HTTPS DAPI URLs with network-specific ports) looks correct and appropriately strict.

Two non-blocking improvements you might consider:

  1. More robust host extraction from entry.address

Using rsplit_once(':') assumes address is always an IPv4-style "host:port". If this ever carries IPv6 or more complex forms, this could misbehave. You can instead parse a synthetic URL to extract the host robustly:

-        let body = response.text().await?;
-        let parsed: MasternodeDiscoveryResponse = serde_json::from_str(&body)?;
+        let parsed: MasternodeDiscoveryResponse = response.json().await?;
@@
-        let mut addresses = Vec::new();
-        for entry in parsed
-            .data
-            .into_iter()
-            .filter(|m| m.status == "ENABLED" && m.version_check.as_deref() == Some("success"))
-        {
-            let host_port = entry.address;
-            let host = host_port
-                .rsplit_once(':')
-                .map(|(h, _)| h)
-                .unwrap_or(host_port.as_str());
-            let https_url = format!("https://{}:{}", host, dapi_port);
+        let mut addresses = Vec::new();
+        for entry in parsed
+            .data
+            .into_iter()
+            .filter(|m| m.status == "ENABLED" && m.version_check.as_deref() == Some("success"))
+        {
+            let host_port = entry.address;
+            let synthetic = format!("scheme://{}", host_port);
+            let parsed_host = Url::parse(&synthetic).map_err(|e| {
+                TrustedContextProviderError::NetworkError(format!(
+                    "Invalid masternode address '{}': {}",
+                    host_port, e
+                ))
+            })?;
+            let host = parsed_host.host_str().ok_or_else(|| {
+                TrustedContextProviderError::NetworkError(format!(
+                    "Masternode address '{}' has no host",
+                    host_port
+                ))
+            })?;
+            let https_url = format!("https://{}:{}", host, dapi_port);
             let url = url::Url::parse(&https_url).map_err(|e| {
                 TrustedContextProviderError::NetworkError(format!(
                     "Invalid masternode URL '{}': {}",
                     https_url, e
                 ))
             })?;
             addresses.push(url);
         }
  1. Use response.json() directly

As shown in the diff, response.json::<MasternodeDiscoveryResponse>().await? is a bit simpler than text() + serde_json::from_str, and keeps deserialization errors clearly associated with the HTTP response.

Both are incremental improvements; the current implementation is functionally fine as-is.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60c7aa6 and 281f9d3.

📒 Files selected for processing (2)
  • packages/rs-sdk-trusted-context-provider/src/provider.rs (3 hunks)
  • packages/wasm-sdk/src/context_provider.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Rust code must pass cargo clippy --workspace linter checks
Rust code must be formatted using cargo fmt --all

**/*.rs: Use 4-space indent for Rust files
Follow rustfmt defaults and keep code clippy-clean for Rust modules
Use snake_case for Rust module names
Use PascalCase for Rust type names
Use SCREAMING_SNAKE_CASE for Rust constants

Files:

  • packages/wasm-sdk/src/context_provider.rs
  • packages/rs-sdk-trusted-context-provider/src/provider.rs
🧬 Code graph analysis (2)
packages/wasm-sdk/src/context_provider.rs (1)
packages/rs-dapi-client/src/address_list.rs (3)
  • uri (65-67)
  • try_from (52-60)
  • from_iter (274-281)
packages/rs-sdk-trusted-context-provider/src/provider.rs (1)
packages/wasm-sdk/src/context_provider.rs (1)
  • fetch_masternode_addresses (137-159)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Rust packages (wasm-sdk) / Unused dependencies
  • GitHub Check: Rust packages (wasm-sdk) / Tests
  • GitHub Check: Rust packages (wasm-sdk) / Linting
  • GitHub Check: Build Docker images (RS-DAPI, rs-dapi, rs-dapi) / Build RS-DAPI image
  • GitHub Check: Build Docker images (Drive, drive, drive-abci) / Build Drive image
  • GitHub Check: Build JS packages / Build JS
  • GitHub Check: Rust crates security audit
🔇 Additional comments (2)
packages/wasm-sdk/src/context_provider.rs (1)

137-159: WASM masternode address conversion is consistent and well-guarded

The flow from discovered URLs → Urirs_dapi_client::AddressAddressList is clean, and the error messages keep the original URL in context, which will be useful for debugging malformed entries. No issues from a correctness or ergonomics standpoint on this path.

packages/rs-sdk-trusted-context-provider/src/provider.rs (1)

27-80: Masternode discovery models correctly capture response shape

MasternodeEntry/MasternodeDiscoveryResponse look appropriate for a { success, data: [...] } response, and the versionCheckversion_check rename plus Option<String> typing is a good fit for potentially missing or failing checks. Deriving Debug/Deserialize here is reasonable and should keep serde integration straightforward.

@github-actions
Copy link

github-actions bot commented Dec 1, 2025

✅ DashSDKFFI.xcframework built for this PR.

SwiftPM (host the zip at a stable URL, then use):

.binaryTarget(
  name: "DashSDKFFI",
  url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",
  checksum: "0e94a349ea1e66f46750967469acc010a55cdae5778fcaa8218b97d40ec70249"
)

Xcode manual integration:

  • Download 'DashSDKFFI.xcframework' artifact from the run link above.
  • Drag it into your app target (Frameworks, Libraries & Embedded Content) and set Embed & Sign.
  • If using the Swift wrapper package, point its binaryTarget to the xcframework location or add the package and place the xcframework at the expected path.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
packages/wasm-sdk/src/sdk.rs (4)

18-72: Global address caches and helpers look correct; a couple of optional robustness tweaks

The new MAINNET_DISCOVERED_ADDRESSES / TESTNET_DISCOVERED_ADDRESSES statics plus parse_addresses, default_*_addresses, and fetch_and_cache_addresses form a coherent flow:

  • parse_addresses correctly reuses Uri parsing and Address::try_from so validation stays centralized.
  • Default mainnet/testnet lists are clearly separated and only used as fallback.
  • fetch_and_cache_addresses cleanly converts the (addr, _status) tuples into a cached Vec<Address> behind a Mutex<Option<_>>, consistent with existing *_TRUSTED_CONTEXT statics. As per coding guidelines, naming and 4‑space indent look good.

Two optional improvements to consider:

  1. Status filtering: if fetch_masternode_addresses can return entries that should not be used (e.g., disabled/banned, wrong version), you might want to filter by _status here instead of ignoring it, to avoid polluting the cache with unusable nodes.
  2. Empty fallback visibility: if parsing ever yielded an empty Vec<Address> (e.g., due to a typo in the hardcoded seeds), this would silently result in an empty AddressList. A debug log or assertion when default_*_addresses() returns empty could make such misconfigurations easier to catch during development.

These are non-blocking; the current implementation is functionally sound.


122-160: prefetchTrustedQuorums* now also fail on masternode discovery errors—confirm intended behavior

The new calls to:

  • fetch_and_cache_addresses(&trusted_context, &MAINNET_DISCOVERED_ADDRESSES) in prefetch_trusted_quorums_mainnet, and
  • fetch_and_cache_addresses(&trusted_context, &TESTNET_DISCOVERED_ADDRESSES) in prefetch_trusted_quorums_testnet

mean that these methods now return an error not only when quorum prefetching fails, but also when masternode address discovery fails.

This tightens the contract: a successful prefetchTrustedQuorums* now implies both quorums and address caches are populated, but it also introduces new failure modes (e.g., if fetch_masternode_addresses is unsupported on some nodes or is more fragile than quorum prefetch).

If backward compatibility of “quorums prefetch rarely fails” is important, you might consider treating address-discovery failure as a soft failure (log + keep existing behavior) rather than bubbling it up, or at least documenting this stronger error condition for callers.


270-313: Mainnet builders correctly prefer discovered addresses with sane fallback; small DRY opportunity

For both:

  • new_mainnet, and
  • new_mainnet_trusted

the pattern:

let mainnet_addresses = MAINNET_DISCOVERED_ADDRESSES
    .lock()
    .unwrap()
    .clone()
    .unwrap_or_else(default_mainnet_addresses);

is correct and nicely ensures:

  • Use of the discovered address cache when prefetchTrustedQuorumsMainnet has run.
  • Fallback to the trimmed hardcoded list when the cache is empty or never populated.

This keeps behavior deterministic and avoids blocking network calls inside the builders. As per coding guidelines, the static name and indentation are also in line with expectations.

Optional refactor: the MAINNET_DISCOVERED_ADDRESSES access + fallback appears twice; extracting a small helper like fn mainnet_addresses() -> Vec<Address> would reduce duplication and keep mainnet behavior in one place. Not required for correctness.


315-358: Testnet builders mirror mainnet logic correctly; consider shared helper for symmetry

Similarly, in:

  • new_testnet, and
  • new_testnet_trusted

the use of TESTNET_DISCOVERED_ADDRESSES with unwrap_or_else(default_testnet_addresses) mirrors mainnet behavior and looks correct:

  • Prefetched addresses are used when available.
  • The hardcoded testnet seeds are used only as a fallback.

This symmetry with mainnet is good for maintainability and caller expectations.

As with mainnet, you could optionally DRY this into a fn testnet_addresses() -> Vec<Address> helper (and/or a generic fn addresses_for(cache, default_fn)) to centralize address-selection logic, but the current duplication is small and acceptable.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 281f9d3 and 494e803.

📒 Files selected for processing (1)
  • packages/wasm-sdk/src/sdk.rs (8 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Rust code must pass cargo clippy --workspace linter checks
Rust code must be formatted using cargo fmt --all

**/*.rs: Use 4-space indent for Rust files
Follow rustfmt defaults and keep code clippy-clean for Rust modules
Use snake_case for Rust module names
Use PascalCase for Rust type names
Use SCREAMING_SNAKE_CASE for Rust constants

Files:

  • packages/wasm-sdk/src/sdk.rs
🧠 Learnings (5)
📚 Learning: 2024-11-28T13:49:17.301Z
Learnt from: shumkov
Repo: dashpay/platform PR: 2317
File: packages/rs-dapi-client/src/address_list.rs:175-180
Timestamp: 2024-11-28T13:49:17.301Z
Learning: In Rust code in `packages/rs-dapi-client/src/address_list.rs`, do not change the interface of deprecated methods like `add_uri`, even to fix potential panics.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
📚 Learning: 2024-10-10T10:30:19.883Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2232
File: packages/rs-sdk/src/mock/sdk.rs:90-95
Timestamp: 2024-10-10T10:30:19.883Z
Learning: In `packages/rs-sdk/src/mock/sdk.rs`, the `load_expectations` method in `MockDashPlatformSdk` remains asynchronous (`async`) for backward compatibility, even though it now delegates to the synchronous `load_expectations_sync` method.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
📚 Learning: 2024-10-30T11:19:59.163Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2277
File: packages/rs-sdk/tests/fetch/config.rs:233-233
Timestamp: 2024-10-30T11:19:59.163Z
Learning: In the Rust SDK's `rs-sdk/tests` integration tests (e.g., in `packages/rs-sdk/tests/fetch/config.rs`), we cannot create objects during tests because there is no support for object creation in this context. Therefore, hardcoded values for test identities must be used.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
📚 Learning: 2024-10-28T10:38:49.538Z
Learnt from: shumkov
Repo: dashpay/platform PR: 2259
File: packages/rs-dapi-client/src/executor.rs:49-56
Timestamp: 2024-10-28T10:38:49.538Z
Learning: In `packages/rs-dapi-client/src/executor.rs`, the `ExecutionResponse` struct always has a non-optional `address` field of type `Address` because an address is always present when there's a successful response.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
📚 Learning: 2025-10-23T13:04:39.160Z
Learnt from: thephez
Repo: dashpay/platform PR: 2816
File: packages/js-dapi-client/lib/networkConfigs.js:17-40
Timestamp: 2025-10-23T13:04:39.160Z
Learning: For the testnet DAPI address whitelist in packages/js-dapi-client/lib/networkConfigs.js, nodes may be intentionally excluded even if they are ENABLED if they are running pre-2.1 versions. Version compatibility is an important filtering criterion beyond just enabled status.

Applied to files:

  • packages/wasm-sdk/src/sdk.rs
🧬 Code graph analysis (1)
packages/wasm-sdk/src/sdk.rs (2)
packages/rs-dapi-client/src/address_list.rs (2)
  • uri (65-67)
  • try_from (52-60)
packages/rs-dapi-client/src/dapi_client.rs (1)
  • address_list (121-123)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Rust packages (wasm-sdk) / Tests
  • GitHub Check: Rust packages (wasm-sdk) / Unused dependencies
  • GitHub Check: Rust packages (wasm-sdk) / Linting
  • GitHub Check: Build Docker images (RS-DAPI, rs-dapi, rs-dapi) / Build RS-DAPI image
  • GitHub Check: Build Docker images (Drive, drive, drive-abci) / Build Drive image
  • GitHub Check: Build JS packages / Build JS
  • GitHub Check: Rust crates security audit
  • GitHub Check: Swift SDK and Example build (warnings as errors)
🔇 Additional comments (1)
packages/wasm-sdk/src/sdk.rs (1)

4-8: Address/Uri imports align with new usage

Top-level Uri and Address imports match their usage in parse_addresses and new_with_addresses, and naming/formatting is consistent with the Rust guidelines for this repo.

lklimek
lklimek previously approved these changes Dec 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In review / testing

Development

Successfully merging this pull request may close these issues.

3 participants