Skip to content

Conversation

thephez
Copy link
Collaborator

@thephez thephez commented Oct 1, 2025

Issue being fixed or feature implemented

The wasm-sdk was not returning groups and tokens fields when fetching data contracts that define tokens, making it impossible to properly work with token contracts through the SDK.

What was done?

Fixed the data contract serialization in wasm-sdk to use the SDK's platform version instead of hardcoded PlatformVersion::first(). This ensures that contracts are serialized using the V1 format which includes groups and tokens fields when the platform version supports it.

Changes made:

  • Modified DataContractWasm struct to store the platform version reference
  • Updated to_json() method to use the stored platform version
  • Fixed all DataContractWasm instantiation points to pass the correct platform version

How Has This Been Tested?

  • Successfully built the wasm-sdk with the changes
  • Verified that the build completes without errors
  • The fix ensures backward compatibility by falling back to PlatformVersion::first() when needed

Breaking Changes

None - This is a backward-compatible fix that preserves existing behavior while enabling proper serialization for newer platform versions.

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

    • Data contracts now carry an explicit platform version so serialization produces platform-version-aware JSON.
    • Fetch and verification flows return data contracts tied to the requested platform version, ensuring consistent versioned behavior.
  • Bug Fixes

    • Improved handling of unknown or mismatched platform versions, returning a clear invalid-argument error instead of defaulting silently.

DataContractWasm was using PlatformVersion::first() which defaults to V0
serialization format that excludes groups and tokens fields. Updated to
use the SDK's platform version for proper V1 serialization support.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

coderabbitai bot commented Oct 1, 2025

Walkthrough

Replaced the tuple-wrapper DataContractWasm(DataContract) with a struct storing contract: DataContract and platform_version: u32. Removed From<DataContract>; added DataContractWasm::from_data_contract(data_contract, platform_version). Callers and (de)serialization now use the stored platform version via PlatformVersion::get(...).

Changes

Cohort / File(s) Summary
DataContractWasm struct & serialization
packages/wasm-sdk/src/dpp.rs
Replaced pub struct DataContractWasm(DataContract); with pub struct DataContractWasm { contract: DataContract, platform_version: u32 }. Removed impl From<DataContract> for DataContractWasm. Added pub(crate) fn from_data_contract(data_contract: DataContract, platform_version: u32) -> Self. Updated method internals to use self.contract and resolve platform versions with PlatformVersion::get(self.platform_version) (instead of PlatformVersion::first()), and adjusted JSON (de)serialization to pass/consult the stored platform version.
Query: return constructed DataContractWasm
packages/wasm-sdk/src/queries/data_contract.rs
get_data_contract now awaits fetch into a local contract variable and returns Ok(DataContractWasm::from_data_contract(contract, self.version())), preserving not-found handling but constructing the new struct with the caller's platform version.
Verification: use new constructor
packages/wasm-sdk/src/verify.rs
verify_data_contract mapping changed from DataContractWasm::from(contract) to DataContractWasm::from_data_contract(contract, PlatformVersion::latest().protocol_version), passing an explicit protocol version when constructing the new struct.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller as Caller
  participant Store as DataContract Store
  participant DCW as DataContractWasm

  Caller->>Store: fetch_by_identifier(...)
  alt found
    Store-->>Caller: DataContract
    Caller->>DCW: DataContractWasm::from_data_contract(contract, version)
    DCW-->>Caller: DataContractWasm { contract, platform_version }
  else not found
    Store-->>Caller: NotFound
  end
Loading
sequenceDiagram
  autonumber
  participant Caller as Caller
  participant DCW as DataContractWasm
  participant PV as PlatformVersion

  Caller->>DCW: to_json()
  DCW->>PV: PlatformVersion::get(self.platform_version)
  alt known
    PV-->>DCW: &PlatformVersion
    DCW-->>Caller: JsValue (serialized using self.contract)
  else unknown
    PV-->>DCW: Err
    DCW-->>Caller: WasmSdkError::invalid_argument
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • QuantumExplorer

Poem

I munched a crate and changed my wrap,
Hopped in a struct to bridge the gap.
Hold your version close and true,
Call to_json — I’ll speak for you. 🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title concisely and accurately summarizes the main change by indicating that the fix in the wasm-sdk now includes the groups and tokens fields during data contract serialization, which directly addresses the core issue described in the PR objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ 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 wasm-sdk-fix-contract-version

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64d590a and fd435e3.

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

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Format Rust code with cargo fmt
Run Clippy linter for Rust code

Files:

  • packages/wasm-sdk/src/queries/data_contract.rs
  • packages/wasm-sdk/src/verify.rs
  • packages/wasm-sdk/src/dpp.rs
packages/wasm-sdk/**

📄 CodeRabbit inference engine (CLAUDE.md)

Keep WASM SDK docs in sync (run generate_docs.py) when updating the WASM SDK

Files:

  • packages/wasm-sdk/src/queries/data_contract.rs
  • packages/wasm-sdk/src/verify.rs
  • packages/wasm-sdk/src/dpp.rs
🧬 Code graph analysis (3)
packages/wasm-sdk/src/queries/data_contract.rs (2)
packages/rs-sdk/src/platform/fetch.rs (1)
  • fetch_by_identifier (242-247)
packages/wasm-sdk/src/dpp.rs (2)
  • id (324-326)
  • from_data_contract (314-319)
packages/wasm-sdk/src/verify.rs (1)
packages/wasm-sdk/src/dpp.rs (1)
  • from_data_contract (314-319)
packages/wasm-sdk/src/dpp.rs (2)
packages/wasm-sdk/src/verify.rs (1)
  • id (188-190)
packages/wasm-sdk/src/error.rs (1)
  • invalid_argument (73-75)
⏰ 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: Rust packages (wasm-sdk) / Formatting
  • 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 (7)
packages/wasm-sdk/src/dpp.rs (5)

298-301: LGTM! Struct definition correctly stores platform version.

The struct now explicitly stores the platform_version alongside the contract, which ensures that serialization operations use the correct platform version rather than defaulting to PlatformVersion::first(). This directly addresses the bug described in the PR objectives where groups and tokens fields were omitted.


303-320: LGTM! Well-documented constructor with required platform version.

The constructor correctly requires an explicit platform_version, preventing the bug where PlatformVersion::first() was used as a fallback. The comprehensive documentation explains the purpose and usage clearly.


324-326: LGTM! Correctly accesses the contract field.

The method correctly adapts to the new struct layout by accessing self.contract instead of the tuple field self.0.


328-354: LGTM! Correct platform version handling in deserialization.

The method correctly:

  1. Validates the platform version before use (line 333)
  2. Uses the validated platform version for deserialization (line 344)
  3. Stores platform_version.protocol_version in the constructed DataContractWasm (line 352)

This ensures consistent version handling throughout the lifecycle of the data contract.


356-374: LGTM! Core fix for serialization bug.

This is the critical change that fixes the issue described in the PR objectives. By using the stored self.platform_version instead of PlatformVersion::first(), the method now correctly serializes version-specific fields like groups and tokens for token contracts.

The error handling is appropriate, converting platform version lookup failures and serialization errors to WasmSdkError.

packages/wasm-sdk/src/queries/data_contract.rs (1)

39-46: LGTM! Correct usage of the new constructor.

The method correctly:

  1. Fetches the data contract with proper error handling (lines 39-41)
  2. Constructs DataContractWasm using from_data_contract with the SDK's platform version (lines 43-46)

This ensures the fetched contract is wrapped with the correct platform version for subsequent serialization operations.

packages/wasm-sdk/src/verify.rs (1)

125-127: LGTM! Correctly updated to use the new constructor.

The verification function now correctly constructs DataContractWasm using from_data_contract with an explicit platform version from PlatformVersion::latest().protocol_version. This aligns with the new requirement that all DataContractWasm instances must be created with an explicit platform version.


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
Collaborator Author

@thephez thephez left a comment

Choose a reason for hiding this comment

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

@coderabbitai review

@thephez thephez added this to the v2.1.0 milestone Oct 1, 2025
@thephez thephez marked this pull request as ready for review October 1, 2025 16:49
@thephez thephez marked this pull request as draft October 1, 2025 16:53
@thephez thephez marked this pull request as ready for review October 1, 2025 17:38
@thephez thephez requested a review from shumkov October 1, 2025 17:38
@thephez
Copy link
Collaborator Author

thephez commented Oct 1, 2025

@coderabbitai full review

Copy link
Contributor

coderabbitai bot commented Oct 1, 2025

✅ Actions performed

Full review triggered.

@dashpay dashpay deleted a comment from coderabbitai bot Oct 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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9d09e7 and 90451af.

📒 Files selected for processing (3)
  • packages/wasm-sdk/src/dpp.rs (2 hunks)
  • packages/wasm-sdk/src/queries/data_contract.rs (1 hunks)
  • packages/wasm-sdk/src/verify.rs (1 hunks)
🔇 Additional comments (3)
packages/wasm-sdk/src/verify.rs (1)

125-125: Consider consistent platform version selection across verification and runtime.

This function uses PlatformVersion::latest() whereas get_data_contract in data_contract.rs uses PlatformVersion::get(self.version()). While this may be acceptable for verification/testing functions, the inconsistency could lead to subtle bugs if verification logic diverges from runtime behavior.

Consider either:

  1. Making verify functions accept a platform version parameter for consistency
  2. Documenting why latest() is appropriate for verification contexts

Based on the PR comments discussion about inconsistent platform version usage.

packages/wasm-sdk/src/dpp.rs (2)

298-298: Document the safety of the 'static lifetime requirement.

The &'static PlatformVersion reference requires that all PlatformVersion instances outlive the DataContractWasm. This is likely safe if PlatformVersion instances are global singletons, but this constraint should be documented.

Consider adding a doc comment explaining:

  • Why 'static is safe (e.g., "PlatformVersion instances are global singletons")
  • Or using a generic lifetime 'a if the 'static constraint is too restrictive

Based on the PR comments about the 'static lifetime concern.


320-326: Core fix correctly implemented.

The to_json method now uses the stored platform version (self.1) instead of the hardcoded PlatformVersion::first(). This ensures that version-specific fields like groups and tokens are included when serializing token contracts.

fn from(value: DataContract) -> Self {
Self(value)
// Use first version as fallback for backward compatibility
Self(value, PlatformVersion::first())
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think this is a safe approach. For now, I would just pass platfrom version to all methods that require it (as rust dpp does). There are non-instance methods and you would need to do it anyway.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Pushed some updates, but I see you've been working on dpp.rs in #2791 so maybe I will pause (since I don't exactly know what I'm doing here 🤪)

thephez and others added 3 commits October 2, 2025 08:53
… methods

Remove unsafe platform version fallback from DataContractWasm:
- Remove stored &'static PlatformVersion field from struct
- Remove From<DataContract> trait implementation using PlatformVersion::first()
- Update toJSON method to accept platform_version parameter
- Add internal from_data_contract helper for codebase use

This ensures platform version is always passed explicitly to methods that require it,
following the same pattern as Rust DPP implementation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
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: 1

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

114-125: Propagate platform version through verify_data_contract

verify_data_contract verifies the proof with PlatformVersion::latest() but returns a DataContractWasm without storing that version, while DataContractWasm.toJSON() requires the caller to supply a version. This risks version mismatches.

Consider updating DataContractWasm::from_data_contract (or its signature) to accept and store the platform version, returning it alongside the contract, or documenting that callers must forward the same version into toJSON().

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90451af and 19ecdda.

📒 Files selected for processing (3)
  • packages/wasm-sdk/src/dpp.rs (2 hunks)
  • packages/wasm-sdk/src/queries/data_contract.rs (1 hunks)
  • packages/wasm-sdk/src/verify.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/wasm-sdk/src/queries/data_contract.rs
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Format Rust code with cargo fmt
Run Clippy linter for Rust code

Files:

  • packages/wasm-sdk/src/verify.rs
  • packages/wasm-sdk/src/dpp.rs
packages/wasm-sdk/**

📄 CodeRabbit inference engine (CLAUDE.md)

Keep WASM SDK docs in sync (run generate_docs.py) when updating the WASM SDK

Files:

  • packages/wasm-sdk/src/verify.rs
  • packages/wasm-sdk/src/dpp.rs
🧬 Code graph analysis (2)
packages/wasm-sdk/src/verify.rs (1)
packages/wasm-sdk/src/dpp.rs (1)
  • from_data_contract (301-303)
packages/wasm-sdk/src/dpp.rs (1)
packages/wasm-sdk/src/error.rs (1)
  • invalid_argument (73-75)
⏰ 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). (6)
  • 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 (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/dpp.rs (2)

313-318: Platform version parameter correctly addresses root cause.

The updated signature requiring an explicit platform_version: u32 parameter directly fixes the original bug where serialization used a hardcoded PlatformVersion::first(). The error handling for unknown platform versions is appropriate.


300-330: Changes align with maintainer guidance and resolve prior concerns.

The removal of the From<DataContract> implementation and the requirement to pass platform_version explicitly to to_json() address both:

  1. The dangerous fallback that could reintroduce the bug (past review comment about PlatformVersion::first())
  2. The maintainer's preference (shumkov's comment) to pass platform version to methods as needed rather than storing it in the struct

This approach correctly ensures that serialization uses the intended platform version for each call, preventing omission of version-specific fields like groups and tokens.

Based on past review comments.

impl From<DataContract> for DataContractWasm {
fn from(value: DataContract) -> Self {
Self(value)
impl DataContractWasm {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I went through DPP methods. Actually, I think your idea to pass the platfrom version to the constructor was the best option we have. But all constructors should always require platform version then. We shouldn't create with default or first version in any case. I'm sorry, that I wasn't clear enough in my first comment, so you reverted half correct code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What about fd435e3?

thephez and others added 3 commits October 6, 2025 16:04
Replace direct Into conversion with from_data_contract method to ensure
proper initialization of DataContractWasm wrapper.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
DataContractWasm now stores platform_version internally as u32, ensuring
consistent version handling across all operations. The toJSON method no
longer requires a platform_version parameter since it uses the stored
value. All constructors now require explicit platform version, following
the pattern that platform version should never use defaults.

BREAKING CHANGE: DataContractWasm.toJSON() no longer accepts a platform_version parameter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants