Skip to content

Comments

feat: implement StateTransitionJsonConvert and fix PlatformAddress map key serialization#3110

Open
Copilot wants to merge 15 commits intov3.1-devfrom
copilot/fix-state-transition-json-conversion
Open

feat: implement StateTransitionJsonConvert and fix PlatformAddress map key serialization#3110
Copilot wants to merge 15 commits intov3.1-devfrom
copilot/fix-state-transition-json-conversion

Conversation

Copy link
Contributor

Copilot AI commented Feb 19, 2026

Problem

StateTransition enum lacked StateTransitionJsonConvert implementation, forcing manual variant matching. Additionally, JSON serialization failed for address-based state transitions containing BTreeMap<PlatformAddress, V> with error "key must be a string" because PlatformAddress (enum with data) serializes as a complex object, violating JSON's string-key requirement.

Investigation revealed both serde_json::to_string_pretty() and to_json() fail identically since to_json() uses platform_value::to_value() internally, which relies on serde.

Changes

StateTransition trait implementations:

  • Created json_conversion.rs - dispatches to_json() to variant implementations
  • Created value_conversion.rs - dispatches conversion methods to variants
  • Implemented StateTransitionFieldTypes returning empty vectors (paths are variant-specific)
  • Added state-transition-json-conversion to dash-sdk-features

PlatformAddress map key serialization fix:

  • Created platform_address_map_serde.rs - custom serde helpers that serialize PlatformAddress keys as Display strings ("P2PKH(hex...)") and deserialize via FromStr
  • Applied to all transitions with BTreeMap<PlatformAddress, ...>:
    • AddressFundsTransferTransitionV0 (inputs, outputs)
    • AddressFundingFromAssetLockTransitionV0 (inputs, outputs)
    • AddressCreditWithdrawalTransitionV0 (inputs)
    • IdentityTopUpFromAddressesTransitionV0 (inputs)
    • IdentityCreateFromAddressesTransitionV0 (inputs)
    • IdentityCreditTransferToAddressesTransitionV0 (recipient_addresses)

WASM bindings update:

  • Added state-transition-json-conversion feature to wasm-dpp2 Cargo.toml to maintain feature parity with wasm-dpp

Result

Both serialization paths now work:

// Serde (now works)
let json = serde_json::to_string_pretty(&state_transition)?;

// Custom (now works)
let json = state_transition.to_json(JsonStateTransitionSerializationOptions::default())?;
{
  "inputs": {
    "P2PKH(0101010101010101010101010101010101010101)": [1, 1000]
  }
}
Original prompt

This section details on the original issue you should resolve

<issue_title>feat: implement StateTransitionJsonConvert for top-level StateTransition enum</issue_title>
<issue_description>## Problem

In packages/rs-dpp/src/state_transition/mod.rs, the StateTransition enum derives Serialize (behind state-transition-serde-conversion feature), but serde_json::to_string_pretty(&state_transition) fails with "key must be a string" for any variant that contains BTreeMap<PlatformAddress, ...> (e.g. AddressFundsTransfer, AddressFundingFromAssetLock, AddressCreditWithdrawal, IdentityCreateFromAddresses, IdentityTopUpFromAddresses, IdentityCreditTransferToAddresses).

This happens because PlatformAddress is an enum that serializes as a complex structure, not a string, and JSON requires all object keys to be strings.

Every individual variant type already implements StateTransitionJsonConvert (which has a to_json() method that properly converts through platform_value::Value, stringifying identifiers and binary data). But the top-level StateTransition enum itself does NOT implement it, forcing consumers to match on all 15 variants manually.

Proposed Fix

Add an impl StateTransitionJsonConvert<'_> for StateTransition that dispatches to each variant's to_json(). This should go in a new file packages/rs-dpp/src/state_transition/json_conversion.rs (gated behind #[cfg(feature = "state-transition-json-conversion")]), similar to how value_conversion.rs or other dispatch files are structured. The implementation:

#[cfg(feature = "state-transition-json-conversion")]
impl StateTransitionJsonConvert<'_> for StateTransition {
    fn to_json(
        &self,
        options: JsonStateTransitionSerializationOptions,
    ) -> Result<serde_json::Value, ProtocolError> {
        match self {
            StateTransition::DataContractCreate(st) => st.to_json(options),
            StateTransition::DataContractUpdate(st) => st.to_json(options),
            StateTransition::Batch(st) => st.to_json(options),
            StateTransition::IdentityCreate(st) => st.to_json(options),
            StateTransition::IdentityTopUp(st) => st.to_json(options),
            StateTransition::IdentityCreditWithdrawal(st) => st.to_json(options),
            StateTransition::IdentityUpdate(st) => st.to_json(options),
            StateTransition::IdentityCreditTransfer(st) => st.to_json(options),
            StateTransition::MasternodeVote(st) => st.to_json(options),
            StateTransition::IdentityCreditTransferToAddresses(st) => st.to_json(options),
            StateTransition::IdentityCreateFromAddresses(st) => st.to_json(options),
            StateTransition::IdentityTopUpFromAddresses(st) => st.to_json(options),
            StateTransition::AddressFundsTransfer(st) => st.to_json(options),
            StateTransition::AddressFundingFromAssetLock(st) => st.to_json(options),
            StateTransition::AddressCreditWithdrawal(st) => st.to_json(options),
        }
    }
}

Note: StateTransitionJsonConvert has a blanket default to_json() that calls self.to_object() (from StateTransitionValueConvert). Since StateTransitionValueConvert is also not implemented for the top-level enum, the explicit override above is needed. It may also make sense to implement StateTransitionValueConvert for StateTransition with the same dispatch pattern.

Also consider adding state-transition-json-conversion to the dash-sdk-features list in packages/rs-dpp/Cargo.toml so SDK consumers get it by default.</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…for StateTransition enum

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix state transition JSON conversion for enum variants feat: implement StateTransitionJsonConvert for top-level StateTransition enum Feb 19, 2026
Copilot AI requested a review from lklimek February 19, 2026 12:13
@github-actions github-actions bot added this to the v3.1.0 milestone Feb 19, 2026
@lklimek lklimek marked this pull request as ready for review February 19, 2026 14:24
@lklimek lklimek changed the title feat: implement StateTransitionJsonConvert for top-level StateTransition enum feat(dpp): implement StateTransitionJsonConvert for top-level StateTransition enum Feb 19, 2026
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
Copilot AI changed the title feat(dpp): implement StateTransitionJsonConvert for top-level StateTransition enum feat: implement StateTransitionJsonConvert for top-level StateTransition enum Feb 19, 2026
Copilot AI and others added 3 commits February 19, 2026 15:47
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
Copilot AI changed the title feat: implement StateTransitionJsonConvert for top-level StateTransition enum feat: implement StateTransitionJsonConvert and fix PlatformAddress map key serialization Feb 19, 2026
Copy link
Collaborator

@shumkov shumkov left a comment

Choose a reason for hiding this comment

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

Please update wasm-dpp2 as well then

@lklimek
Copy link
Contributor

lklimek commented Feb 20, 2026

@copilot Please update wasm-dpp2 to match changes in this PR.

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 20, 2026

Please update wasm-dpp2 as well then

Updated in commit 314a1c6. Added state-transition-json-conversion feature to wasm-dpp2 Cargo.toml to match wasm-dpp.

@copilot Please update wasm-dpp2 to match changes in this PR.

Done in commit 314a1c6. Added state-transition-json-conversion feature to wasm-dpp2/Cargo.toml dependencies.

…then docs

Replace verbose println-based tests with proper assertion-based tests
that validate both to_json() and serde_json serialization paths produce
correct string keys for BTreeMap<PlatformAddress, V> fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@lklimek lklimek force-pushed the copilot/fix-state-transition-json-conversion branch from 61a90c0 to 5a43766 Compare February 23, 2026 12:47
lklimek and others added 2 commits February 23, 2026 13:50
Remove duplicated test functions, keep the consolidated versions
with shared helper, proper assertions, and given/when/then docstrings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verify that StateTransition::to_json() and serde_json serialization
work correctly in the wasm-dpp2 context with its enabled features,
including string keys for BTreeMap<PlatformAddress, V> fields.

Co-Authored-By: Claude Opus 4.6 <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.

feat: implement StateTransitionJsonConvert for top-level StateTransition enum

3 participants