Skip to content

feat(sdk): auto-detect and update platform protocol version from network epoch info #3410

@lklimek

Description

@lklimek

Problem

The SDK's PlatformVersion is set at build time via SdkBuilder::with_version() and stored as a fixed &'static PlatformVersion inside SdkInstance. There is no mechanism to update it at runtime based on the actual network state.

This causes two problems:

  1. Feature gating: Applications cannot determine which Platform features are available on the connected network. For example, shielded transactions (ZK) will only be available starting from Platform v3.1 (protocol version 12+). Without knowing the network's actual protocol version, the app cannot hide unavailable features.

  2. Version mismatch: If the SDK is compiled with protocol version 12 but the connected network is still on version 11, state transitions built with v12 serialization may be rejected. The SDK should ideally match the network's version.

Current State

  • SdkBuilder::with_version() sets the version at initialization — &'static PlatformVersion
  • Sdk::version() returns the build-time version, never updated
  • ExtendedEpochInfo::fetch_current() returns protocol_version() — the live network protocol version from the current epoch
  • PlatformVersion::get(version: u32) can look up the &'static PlatformVersion for a given protocol version number
  • PlatformVersionCurrentVersion::set_current() exists as a global RwLock setter in DPP, but the SDK doesn't use it

Proposed Solution

1. Add Sdk::update_version_from_network() method

impl Sdk {
    /// Fetch the current epoch info from the network and update the SDK's
    /// protocol version to match. Call this periodically (e.g., on epoch change)
    /// or after initial connection.
    pub async fn update_version_from_network(&self) -> Result<&'static PlatformVersion, Error> {
        let epoch_info = ExtendedEpochInfo::fetch_current(self).await?;
        let network_version = epoch_info.protocol_version();
        let platform_version = PlatformVersion::get(network_version)?;
        self.set_version(platform_version);
        Ok(platform_version)
    }
}

2. Add Sdk::set_version() runtime setter

The current SdkInstance stores version: &'static PlatformVersion as a plain field. To allow runtime updates:

  • Wrap the version field in an ArcSwap<&'static PlatformVersion> or similar lock-free atomic pointer
  • Add pub fn set_version(&self, version: &'static PlatformVersion) that updates the stored version
  • Sdk::version() continues to return &'static PlatformVersion — reads are zero-cost with ArcSwap::load()

3. Expose Sdk::protocol_version() convenience method

impl Sdk {
    /// Returns the numeric protocol version (e.g., 11, 12).
    pub fn protocol_version(&self) -> u32 {
        self.version().protocol_version
    }
}

4. Also update PlatformVersionCurrentVersion::set_current()

When set_version() is called, also call PlatformVersionCurrentVersion::set_current() so that DPP code using the global version stays in sync.

Use Cases

Feature gating in Dash Evo Tool

// After connecting to network:
sdk.update_version_from_network().await?;

// Gate shielded features:
if sdk.protocol_version() >= 12 {
    // Show shielded tab, enable shielded MCP tools
}

Automatic version tracking

// On each epoch info refresh (periodic task):
let epoch_info = ExtendedEpochInfo::fetch_current(&sdk).await?;
let new_version = epoch_info.protocol_version();
if new_version != sdk.protocol_version() {
    sdk.set_version(PlatformVersion::get(new_version)?);
    tracing::info!("Platform protocol version updated: {new_version}");
}

Files Affected

File Change
packages/rs-sdk/src/sdk.rs Add set_version(), update_version_from_network(), protocol_version()
packages/rs-sdk/src/sdk.rs (SdkInstance) Wrap version field in ArcSwap or similar

Acceptance Criteria

  • Sdk::set_version() updates the protocol version at runtime
  • Sdk::update_version_from_network() fetches epoch info and updates version
  • Sdk::protocol_version() returns the numeric protocol version
  • PlatformVersionCurrentVersion::set_current() is called on version update
  • Sdk::version() remains backward-compatible (returns &'static PlatformVersion)
  • Thread-safe: concurrent reads of version() during set_version() are safe

🤖 Co-authored by Claudius the Magnificent AI Agent

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions