From 9c97995edf522fe08e8fe0345c633f50000f8316 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 1 Sep 2026 13:28:43 +0200 Subject: [PATCH 1/2] fix(dpp): surface identifier-typed document properties as base58 in JS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Document properties getter serialized Value::Identifier through the non-human-readable serde path, so identifier-typed properties (typed by binary document deserialization and index-key synthesis alike) reached JS as Uint8Array. The chained-query surface documents them as base58 — the form where-clauses accept back as a pagination cursor — and the platform-test-suite asserts it, failing the Test Suite and browser CI jobs on every PR since #4567. Convert Value::Identifier values to base58 strings in the properties getter (map keys already got this via stringify_map_keys_for_object); other binary properties stay Uint8Array, and toObject/toJSON are unchanged. Co-Authored-By: Claude Fable 5 --- .../src/data_contract/document/model.rs | 7 +++- .../src/serialization/conversions.rs | 35 +++++++++++++++++ .../wasm-dpp2/tests/unit/Document.spec.ts | 38 +++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/packages/wasm-dpp2/src/data_contract/document/model.rs b/packages/wasm-dpp2/src/data_contract/document/model.rs index b49d54ff9a3..525119515cb 100644 --- a/packages/wasm-dpp2/src/data_contract/document/model.rs +++ b/packages/wasm-dpp2/src/data_contract/document/model.rs @@ -289,7 +289,12 @@ impl DocumentWasm { .map(|(k, v)| (Value::Text(k.clone()), v.clone())) .collect(), ); - let js_value = serialization::platform_value_to_object(&properties_value)?; + // Identifier-typed properties surface as base58 strings — the + // form where-clauses accept back, so a proven join value can be + // used as a pagination cursor directly. Other binary properties + // stay Uint8Array. + let js_value = + serialization::platform_value_to_object_with_base58_identifiers(&properties_value)?; Ok(js_value.into()) } diff --git a/packages/wasm-dpp2/src/serialization/conversions.rs b/packages/wasm-dpp2/src/serialization/conversions.rs index 6c1063f81d1..df0e0acc547 100644 --- a/packages/wasm-dpp2/src/serialization/conversions.rs +++ b/packages/wasm-dpp2/src/serialization/conversions.rs @@ -374,6 +374,41 @@ fn stringify_key(key: &platform_value::Value) -> platform_value::Value { } } +/// Serialize platform_value::Value to JsValue as a JS object like +/// [`platform_value_to_object`], but with `Value::Identifier` VALUES as +/// base58 strings (matching the `Identifier` JSON convention and the +/// base58 form query where-clauses accept). `Value::Bytes*` still become +/// Uint8Array. This is the document `properties` surface: every typed +/// decode path (binary document deserialization, index-key synthesis) +/// produces `Value::Identifier` for identifier-typed properties, so the +/// variant alone marks them — no document-type schema is needed here. +pub fn platform_value_to_object_with_base58_identifiers( + value: &platform_value::Value, +) -> WasmDppResult { + platform_value_to_object(&identifier_values_to_base58(value)) +} + +/// Recursively convert `Value::Identifier` values to base58 `Value::Text`. +/// Map keys are left alone — [`stringify_map_keys_for_object`] already +/// renders identifier keys as base58. +fn identifier_values_to_base58(value: &platform_value::Value) -> platform_value::Value { + use dpp::platform_value::Value; + use dpp::platform_value::string_encoding::{Encoding, encode}; + match value { + Value::Identifier(bytes) => Value::Text(encode(bytes, Encoding::Base58)), + Value::Map(entries) => Value::Map( + entries + .iter() + .map(|(k, v)| (k.clone(), identifier_values_to_base58(v))) + .collect(), + ), + Value::Array(items) => { + Value::Array(items.iter().map(identifier_values_to_base58).collect()) + } + other => other.clone(), + } +} + /// Serialize platform_value::Value to JsValue as JSON-compatible (human-readable). /// /// Converts Value::Identifier and Value::Bytes to base58/base64 strings for JSON compatibility. diff --git a/packages/wasm-dpp2/tests/unit/Document.spec.ts b/packages/wasm-dpp2/tests/unit/Document.spec.ts index 451aed813cb..82b5d3a88e9 100644 --- a/packages/wasm-dpp2/tests/unit/Document.spec.ts +++ b/packages/wasm-dpp2/tests/unit/Document.spec.ts @@ -256,6 +256,44 @@ describe('Document', () => { expect(documentInstance.properties).to.deep.equal(document2); }); + + it('should surface identifier-typed properties as base58 strings', () => { + const contractWithIdentifier = { + ...dataContractValue, + documentSchemas: { + note: { + type: 'object', + properties: { + message: { type: 'string', position: 0 }, + authorId: { + type: 'array', + byteArray: true, + contentMediaType: 'application/x.dash.dpp.identifier', + minItems: 32, + maxItems: 32, + position: 1, + }, + }, + additionalProperties: false, + }, + }, + }; + const dataContract = wasm.DataContract.fromJSON(contractWithIdentifier, false); + const documentInstance = createDocument({ + id, + properties: { message: 'hi', authorId: id }, + dataContractId: dataContract.id.toBase58(), + }); + + const bytes = documentInstance.toBytes(dataContract, new PlatformVersion(1)); + const restored = wasm.Document.fromBytes(bytes, dataContract, 'note', new PlatformVersion(1)); + + // The schema-typed decode yields Value::Identifier for authorId, + // and the properties getter surfaces it as base58 — the form + // where-clauses accept back as a cursor. + expect(restored.properties.authorId).to.equal(id); + expect(restored.properties.message).to.equal('hi'); + }); }); describe('revision', () => { From a768cebc3459cbf3fa552ca449fd22295950eefa Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 1 Sep 2026 13:30:14 +0200 Subject: [PATCH 2/2] ci: run the test suite when wasm-dpp2 or js-evo-sdk change The suite drives the network through @dashevo/evo-sdk (wasm-dpp2 under it) since the chained-query coverage landed, but neither package was in the e2e-tests-changed filter, so changes to them shipped without the suite running. Co-Authored-By: Claude Fable 5 --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index df762654135..bfbb7183c65 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -102,6 +102,8 @@ jobs: - packages/js-dash-sdk/** - packages/wallet-lib/** - packages/wasm-sdk/** + - packages/wasm-dpp2/** + - packages/js-evo-sdk/** - packages/dapi/.env.example - packages/rs-drive-abci/.env.local - .github/actions/aws_ecr_login/**