Skip to content

Conversation

@shumkov
Copy link
Collaborator

@shumkov shumkov commented Nov 11, 2025

Issue being fixed or feature implemented

JSON doesn't support integer as a key for object

What was done?

  • Implemented fallback to string keys in maps to support JSON deserialisations

How Has This Been Tested?

With test

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

    • Data contracts now accept and normalize flexible JSON input formats, handling both numeric and string-formatted keys for token distributions and pre-programmed distribution timestamps.
  • Tests

    • Added unit tests validating JSON-to-data-contract parsing succeeds for stepwise and pre-programmed distributions using various key formats.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 11, 2025

Walkthrough

Custom deserializers were added to accept numeric or string keys for distribution maps, normalizing them into BTreeMap<u64, ...> shapes for stepwise and timestamped pre-programmed distributions. Two unit tests verify deserialization succeeds with string-key inputs.

Changes

Cohort / File(s) Change Summary
Perpetual Stepwise distribution
packages/rs-dpp/src/data_contract/associated_token/token_perpetual_distribution/distribution_function/mod.rs
DistributionFunction::Stepwise now uses #[serde(deserialize_with = "deserialize_u64_token_amount_map")] and a new public helper deserialize_u64_token_amount_map was added to accept either numeric (BTreeMap<u64, TokenAmount>) or string-key maps and normalize to BTreeMap<u64, TokenAmount>.
Pre-programmed distribution (v0)
packages/rs-dpp/src/data_contract/associated_token/token_pre_programmed_distribution/v0/mod.rs
TokenPreProgrammedDistributionV0.distributions now has #[serde(deserialize_with = "deserialize_ts_to_id_amount_map")]. A new internal helper deserialize_ts_to_id_amount_map was added to accept numeric or string timestamp keys and normalize to BTreeMap<TimestampMillis, BTreeMap<Identifier, TokenAmount>>.
JSON conversion tests
packages/rs-dpp/src/data_contract/conversion/json/mod.rs
Added unit tests verifying DataContract::from_json accepts stepwise distributions with string keys and pre-programmed distributions with string timestamp keys using full validation.

Sequence Diagram(s)

sequenceDiagram
    participant JSON as JSON Input
    participant Serde as serde deserializer
    participant Norm as Normalizer
    participant Map as BTreeMap Output

    JSON->>Serde: deserialize field (Stepwise / distributions)
    Serde->>Norm: receive either U64-map or Str-map (untagged enum)
    alt U64 map
        Norm->>Map: return BTreeMap<u64, Value> unchanged
    else Str map
        Norm->>Norm: parse each string key -> u64 (error on parse fail)
        Norm->>Map: construct normalized BTreeMap<u64, Value>
    end
    Map-->>Serde: normalized map returned to struct
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review focus:
    • Correct serde attribute placements and visibility of new helper functions.
    • Robust error messages and handling when parsing string keys to u64.
    • Preservation of ordering semantics (BTreeMap) after key conversion.
    • Unit tests correctness and coverage for both success and failure cases.

Poem

🐰 I parsed strings and numbers too,

Keys hopped in line, all shiny and new.
From text to u64 they gracefully flew,
One BTreeMap now holds the crew—
A rabbit's cheer for code made true! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title refers to fixing deserialization of data contract JSON with token configuration, which matches the core change: implementing fallback to string keys for maps during JSON deserialization. However, the title contains a typo ('desiarilization' instead of 'deserialization') and is somewhat vague about the specific technical approach.
✨ 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 fix/data-contract-from-json-maps

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.

@shumkov shumkov moved this to In review / testing in Platform team Nov 11, 2025
@shumkov shumkov self-assigned this Nov 11, 2025
@shumkov shumkov changed the title fix: data contract json maps fix!(dpp): data contract json maps Nov 11, 2025
@shumkov shumkov changed the title fix!(dpp): data contract json maps fix!(dpp): desiarilization of data contract JSON with token configuration Nov 11, 2025
@shumkov shumkov changed the title fix!(dpp): desiarilization of data contract JSON with token configuration fix(dpp)!: desiarilization of data contract JSON with token configuration Nov 11, 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-dpp/src/data_contract/associated_token/token_perpetual_distribution/distribution_function/mod.rs (1)

564-601: Well-implemented custom deserializer with clear documentation.

The deserializer correctly normalizes both numeric and string JSON keys into BTreeMap<u64, TokenAmount>, with proper error handling for invalid string keys.

Note: This deserializer follows a nearly identical pattern to deserialize_ts_to_id_amount_map in token_pre_programmed_distribution/v0/mod.rs. If this pattern is used elsewhere in the future, consider extracting a generic helper to reduce duplication. For now, the duplication is minimal 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 912ac2a and ba19710.

📒 Files selected for processing (3)
  • packages/rs-dpp/src/data_contract/associated_token/token_perpetual_distribution/distribution_function/mod.rs (2 hunks)
  • packages/rs-dpp/src/data_contract/associated_token/token_pre_programmed_distribution/v0/mod.rs (2 hunks)
  • packages/rs-dpp/src/data_contract/conversion/json/mod.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • packages/rs-dpp/src/data_contract/associated_token/token_perpetual_distribution/distribution_function/mod.rs
  • packages/rs-dpp/src/data_contract/conversion/json/mod.rs
  • packages/rs-dpp/src/data_contract/associated_token/token_pre_programmed_distribution/v0/mod.rs
🧠 Learnings (4)
📓 Common learnings
Learnt from: lklimek
Repo: dashpay/platform PR: 2277
File: packages/dapi-grpc/src/mock.rs:125-145
Timestamp: 2024-10-29T14:16:00.141Z
Learning: Using `serde_json` encoding produces deterministic output required to identify requests and responses by hash, therefore `serde_json` is used as the basic serialization algorithm for mocking.
📚 Learning: 2025-04-11T09:08:05.652Z
Learnt from: pauldelucia
Repo: dashpay/platform PR: 2523
File: packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs:147-151
Timestamp: 2025-04-11T09:08:05.652Z
Learning: Description length validation for data contracts is already handled in the data contract validation process, specifically in packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs.

Applied to files:

  • packages/rs-dpp/src/data_contract/conversion/json/mod.rs
📚 Learning: 2024-12-10T10:56:26.215Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2030
File: packages/rs-sdk/tests/vectors/test_asset_lock_proof/quorum_pubkey-100-4ce7fd81273c2b394c0f32367374fc5b09ba912e017aacb366d2171e9ca6f9d5.json:1-1
Timestamp: 2024-12-10T10:56:26.215Z
Learning: In the `packages/rs-sdk/tests/vectors/test_asset_lock_proof/` directory, files with the `.json` extension are mock data that may not follow standard JSON format; this is intentional and acceptable within the project's testing framework.

Applied to files:

  • packages/rs-dpp/src/data_contract/conversion/json/mod.rs
📚 Learning: 2024-10-29T14:16:00.141Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2277
File: packages/dapi-grpc/src/mock.rs:125-145
Timestamp: 2024-10-29T14:16:00.141Z
Learning: Using `serde_json` encoding produces deterministic output required to identify requests and responses by hash, therefore `serde_json` is used as the basic serialization algorithm for mocking.

Applied to files:

  • packages/rs-dpp/src/data_contract/associated_token/token_pre_programmed_distribution/v0/mod.rs
🧬 Code graph analysis (1)
packages/rs-dpp/src/data_contract/associated_token/token_perpetual_distribution/distribution_function/mod.rs (3)
packages/rs-dpp/src/data_contract/v0/serialization/mod.rs (1)
  • deserialize (26-45)
packages/rs-dpp/src/identity/state_transition/asset_lock_proof/mod.rs (1)
  • deserialize (58-84)
packages/rs-dpp/src/data_contract/associated_token/token_pre_programmed_distribution/v0/mod.rs (1)
  • k (66-66)
⏰ 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). (17)
  • GitHub Check: Rust packages (drive-abci) / Tests
  • GitHub Check: Rust packages (drive) / Tests
  • GitHub Check: Rust packages (wasm-dpp2) / Tests
  • GitHub Check: Rust packages (wasm-sdk) / Tests
  • GitHub Check: Rust packages (rs-sdk-ffi) / Tests
  • GitHub Check: Rust packages (dash-sdk) / Tests
  • GitHub Check: Rust packages (wasm-dpp) / Tests
  • GitHub Check: Rust packages (dpp) / Check each feature
  • GitHub Check: Rust packages (dpp) / Tests
  • GitHub Check: Rust packages (dpp) / Unused dependencies
  • GitHub Check: Rust packages (dpp) / Linting
  • GitHub Check: Build Docker images (Dashmate helper, dashmate-helper, dashmate-helper) / Build Dashmate helper image
  • 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 (4)
packages/rs-dpp/src/data_contract/conversion/json/mod.rs (1)

56-341: LGTM! Comprehensive test coverage for string key deserialization.

The tests correctly validate that both stepwise distributions (with string step keys) and preprogrammed distributions (with string timestamp keys) are accepted by from_json. Using full_validation = true ensures the deserialized contracts pass all validation rules.

packages/rs-dpp/src/data_contract/associated_token/token_perpetual_distribution/distribution_function/mod.rs (1)

162-165: LGTM! Proper application of custom deserializer.

The custom deserializer is correctly applied to the Stepwise variant, enabling acceptance of both numeric and string keys in JSON input.

packages/rs-dpp/src/data_contract/associated_token/token_pre_programmed_distribution/v0/mod.rs (2)

31-72: LGTM! Clean implementation of timestamp key deserializer.

The deserializer correctly normalizes both numeric and string timestamp keys into the expected BTreeMap<TimestampMillis, BTreeMap<Identifier, TokenAmount>> structure, with proper error handling.


13-14: LGTM! Correct deserializer application.

The custom deserializer is properly applied to the distributions field, enabling flexible JSON input with either numeric or string timestamp keys.

@github-actions
Copy link

github-actions bot commented Nov 11, 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: "66dbfc66abb1b6ba939903d97706b858ab068ced56c8aba5fa9a7f0b66d1e4cb"
)

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.

@shumkov shumkov changed the title fix(dpp)!: desiarilization of data contract JSON with token configuration fix(dpp): desiarilization of data contract JSON with token configuration Nov 12, 2025
@shumkov shumkov merged commit 71ea33d into v2.2-dev Nov 12, 2025
86 checks passed
@shumkov shumkov deleted the fix/data-contract-from-json-maps branch November 12, 2025 11:33
@github-project-automation github-project-automation bot moved this from In review / testing to Done in Platform team Nov 12, 2025
@shumkov shumkov changed the title fix(dpp): desiarilization of data contract JSON with token configuration fix(dpp): deserialization of data contract JSON with token configuration Nov 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants