@dashevo/wasm-dpp 4.0.0 → 4.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +0 -4
- package/dist/wasm/wasm_dpp.d.ts +964 -966
- package/dist/wasm/wasm_dpp.js +57 -60
- package/dist/wasm/wasm_dpp_bg.js +1 -1
- package/lib/wasm/wasm_dpp.d.ts +964 -966
- package/package.json +2 -2
- package/src/data_contract/data_contract.rs +11 -14
- package/src/data_contract/state_transition/data_contract_create_transition/mod.rs +40 -13
- package/src/data_contract/state_transition/data_contract_update_transition/mod.rs +40 -13
- package/src/document/extended_document.rs +17 -60
- package/src/document/mod.rs +22 -5
- package/src/identity/state_transition/asset_lock_proof/chain/chain_asset_lock_proof.rs +4 -1
- package/src/identity/state_transition/asset_lock_proof/instant/instant_asset_lock_proof.rs +5 -1
- package/src/utils.rs +51 -1
- package/test/integration/document/Document.spec.js +0 -60
- package/test/unit/dataContract/DataContract.spec.js +22 -2
- package/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js +1 -1
- package/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js +3 -2
- package/test/unit/document/Document.spec.js +0 -22
- package/test/unit/document/DocumentFactory.spec.js +2 -4
- package/test/unit/document/errors/InvalidDocumentError.spec.js +5 -4
- package/test/unit/identity/Identity.spec.js +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dashevo/wasm-dpp",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.1.0-beta.2",
|
|
4
4
|
"description": "The JavaScript implementation of the Dash Platform Protocol",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@babel/core": "^7.26.10",
|
|
45
45
|
"@babel/preset-env": "^7.26.9",
|
|
46
46
|
"@dashevo/dashcore-lib": "~0.22.0",
|
|
47
|
-
"@dashevo/dpns-contract": "4.0.
|
|
47
|
+
"@dashevo/dpns-contract": "4.1.0-beta.2",
|
|
48
48
|
"@types/bs58": "^4.0.1",
|
|
49
49
|
"@types/node": "^20.10.0",
|
|
50
50
|
"@yarnpkg/pnpify": "^4.0.0-rc.42",
|
|
@@ -13,7 +13,6 @@ use dpp::platform_value::{platform_value, Value};
|
|
|
13
13
|
use dpp::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters};
|
|
14
14
|
use dpp::data_contract::accessors::v1::DataContractV1Getters;
|
|
15
15
|
use dpp::data_contract::config::DataContractConfig;
|
|
16
|
-
use dpp::data_contract::conversion::json::DataContractJsonConversionMethodsV0;
|
|
17
16
|
use dpp::data_contract::conversion::value::v0::DataContractValueConversionMethodsV0;
|
|
18
17
|
use dpp::data_contract::created_data_contract::CreatedDataContract;
|
|
19
18
|
use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
|
|
@@ -102,13 +101,11 @@ impl DataContractWasm {
|
|
|
102
101
|
|
|
103
102
|
let platform_version = PlatformVersion::first();
|
|
104
103
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
.with_js_error()
|
|
111
|
-
.map(Into::into)
|
|
104
|
+
let value = raw_parameters.with_serde_to_platform_value()?;
|
|
105
|
+
let full_validation = !skip_validation;
|
|
106
|
+
DataContract::from_value(value, full_validation, platform_version)
|
|
107
|
+
.with_js_error()
|
|
108
|
+
.map(Into::into)
|
|
112
109
|
}
|
|
113
110
|
|
|
114
111
|
#[wasm_bindgen(js_name=getId)]
|
|
@@ -326,9 +323,9 @@ impl DataContractWasm {
|
|
|
326
323
|
|
|
327
324
|
#[wasm_bindgen(js_name=toObject)]
|
|
328
325
|
pub fn to_object(&self) -> Result<JsValue, JsValue> {
|
|
329
|
-
let
|
|
330
|
-
|
|
331
|
-
|
|
326
|
+
let value = dpp::platform_value::to_value(&self.inner)
|
|
327
|
+
.map_err(ProtocolError::ValueError)
|
|
328
|
+
.with_js_error()?;
|
|
332
329
|
|
|
333
330
|
let serializer = serde_wasm_bindgen::Serializer::json_compatible();
|
|
334
331
|
|
|
@@ -370,9 +367,9 @@ impl DataContractWasm {
|
|
|
370
367
|
|
|
371
368
|
#[wasm_bindgen(js_name=toJSON)]
|
|
372
369
|
pub fn to_json(&self) -> Result<JsValue, JsValue> {
|
|
373
|
-
let
|
|
374
|
-
|
|
375
|
-
|
|
370
|
+
let json = serde_json::to_value(&self.inner)
|
|
371
|
+
.map_err(|e| ProtocolError::EncodingError(e.to_string()))
|
|
372
|
+
.with_js_error()?;
|
|
376
373
|
let serializer = serde_wasm_bindgen::Serializer::json_compatible();
|
|
377
374
|
with_js_error!(json.serialize(&serializer))
|
|
378
375
|
}
|
|
@@ -15,7 +15,9 @@ use dpp::state_transition::{
|
|
|
15
15
|
StateTransitionIdentitySigned, StateTransitionOwned, StateTransitionSingleSigned,
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
use dpp::
|
|
18
|
+
use dpp::serialization::ValueConvertible;
|
|
19
|
+
use dpp::state_transition::StateTransition;
|
|
20
|
+
use dpp::state_transition::StateTransitionFieldTypes;
|
|
19
21
|
use dpp::version::PlatformVersion;
|
|
20
22
|
use dpp::{state_transition::StateTransitionLike, ProtocolError};
|
|
21
23
|
use serde::Serialize;
|
|
@@ -47,14 +49,32 @@ impl From<DataContractCreateTransitionWasm> for DataContractCreateTransition {
|
|
|
47
49
|
impl DataContractCreateTransitionWasm {
|
|
48
50
|
#[wasm_bindgen(constructor)]
|
|
49
51
|
pub fn new(value: JsValue) -> Result<DataContractCreateTransitionWasm, JsValue> {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
use dpp::platform_value::Value;
|
|
53
|
+
let mut raw = value.with_serde_to_platform_value()?;
|
|
54
|
+
// Canonical `ValueConvertible::from_object` is a strict serde
|
|
55
|
+
// deserialization: it dispatches on the enum's `$formatVersion` tag and
|
|
56
|
+
// requires every field. Legacy JS clients construct a transition from
|
|
57
|
+
// its essential inputs (data contract + identity nonce) and sign it
|
|
58
|
+
// afterwards, so default the format tag plus the protocol-managed and
|
|
59
|
+
// signature fields they omit — preserving the lenient construction the
|
|
60
|
+
// pre-canonical path provided.
|
|
61
|
+
if let Value::Map(ref mut entries) = raw {
|
|
62
|
+
let mut ensure = |key: &str, default: Value| {
|
|
63
|
+
if !entries
|
|
64
|
+
.iter()
|
|
65
|
+
.any(|(k, _)| matches!(k, Value::Text(s) if s == key))
|
|
66
|
+
{
|
|
67
|
+
entries.push((Value::Text(key.to_string()), default));
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
ensure("$formatVersion", Value::Text("0".to_string()));
|
|
71
|
+
ensure("userFeeIncrease", Value::U16(0));
|
|
72
|
+
ensure("signaturePublicKeyId", Value::U32(0));
|
|
73
|
+
ensure("signature", Value::Bytes(vec![]));
|
|
74
|
+
}
|
|
75
|
+
DataContractCreateTransition::from_object(raw)
|
|
76
|
+
.map(Into::into)
|
|
77
|
+
.with_js_error()
|
|
58
78
|
}
|
|
59
79
|
|
|
60
80
|
#[wasm_bindgen(js_name=getDataContract)]
|
|
@@ -187,10 +207,17 @@ impl DataContractCreateTransitionWasm {
|
|
|
187
207
|
|
|
188
208
|
#[wasm_bindgen(js_name=toObject)]
|
|
189
209
|
pub fn to_object(&self, skip_signature: Option<bool>) -> Result<JsValue, JsValue> {
|
|
190
|
-
let serde_object = self
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
210
|
+
let mut serde_object = self.0.to_object().map_err(from_protocol_error)?;
|
|
211
|
+
|
|
212
|
+
if skip_signature.unwrap_or(false) {
|
|
213
|
+
for path in
|
|
214
|
+
<DataContractCreateTransition as StateTransitionFieldTypes>::signature_property_paths()
|
|
215
|
+
{
|
|
216
|
+
serde_object
|
|
217
|
+
.remove_values_matching_path(path)
|
|
218
|
+
.map_err(|e| from_protocol_error(dpp::ProtocolError::ValueError(e)))?;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
194
221
|
|
|
195
222
|
let serializer = serde_wasm_bindgen::Serializer::json_compatible();
|
|
196
223
|
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
// pub use validation::*;
|
|
4
4
|
|
|
5
5
|
use dpp::consensus::ConsensusError;
|
|
6
|
+
use dpp::serialization::ValueConvertible;
|
|
6
7
|
use dpp::serialization::{PlatformDeserializable, PlatformSerializable};
|
|
7
8
|
use dpp::state_transition::data_contract_update_transition::accessors::DataContractUpdateTransitionAccessorsV0;
|
|
8
9
|
use dpp::state_transition::data_contract_update_transition::DataContractUpdateTransition;
|
|
10
|
+
use dpp::state_transition::StateTransition;
|
|
11
|
+
use dpp::state_transition::StateTransitionFieldTypes;
|
|
9
12
|
use dpp::state_transition::StateTransitionHasUserFeeIncrease;
|
|
10
|
-
use dpp::state_transition::{StateTransition, StateTransitionValueConvert};
|
|
11
13
|
use dpp::state_transition::{
|
|
12
14
|
StateTransitionIdentitySigned, StateTransitionOwned, StateTransitionSingleSigned,
|
|
13
15
|
};
|
|
@@ -48,14 +50,32 @@ impl From<DataContractUpdateTransitionWasm> for DataContractUpdateTransition {
|
|
|
48
50
|
impl DataContractUpdateTransitionWasm {
|
|
49
51
|
#[wasm_bindgen(constructor)]
|
|
50
52
|
pub fn new(raw_parameters: JsValue) -> Result<DataContractUpdateTransitionWasm, JsValue> {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
use dpp::platform_value::Value;
|
|
54
|
+
let mut raw = raw_parameters.with_serde_to_platform_value()?;
|
|
55
|
+
// Canonical `ValueConvertible::from_object` is a strict serde
|
|
56
|
+
// deserialization: it dispatches on the enum's `$formatVersion` tag and
|
|
57
|
+
// requires every field. Legacy JS clients construct a transition from
|
|
58
|
+
// its essential inputs (data contract + identity contract nonce) and
|
|
59
|
+
// sign it afterwards, so default the format tag plus the
|
|
60
|
+
// protocol-managed and signature fields they omit — preserving the
|
|
61
|
+
// lenient construction the pre-canonical path provided.
|
|
62
|
+
if let Value::Map(ref mut entries) = raw {
|
|
63
|
+
let mut ensure = |key: &str, default: Value| {
|
|
64
|
+
if !entries
|
|
65
|
+
.iter()
|
|
66
|
+
.any(|(k, _)| matches!(k, Value::Text(s) if s == key))
|
|
67
|
+
{
|
|
68
|
+
entries.push((Value::Text(key.to_string()), default));
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
ensure("$formatVersion", Value::Text("0".to_string()));
|
|
72
|
+
ensure("userFeeIncrease", Value::U16(0));
|
|
73
|
+
ensure("signaturePublicKeyId", Value::U32(0));
|
|
74
|
+
ensure("signature", Value::Bytes(vec![]));
|
|
75
|
+
}
|
|
76
|
+
DataContractUpdateTransition::from_object(raw)
|
|
77
|
+
.map(Into::into)
|
|
78
|
+
.with_js_error()
|
|
59
79
|
}
|
|
60
80
|
|
|
61
81
|
#[wasm_bindgen(js_name=getDataContract)]
|
|
@@ -191,10 +211,17 @@ impl DataContractUpdateTransitionWasm {
|
|
|
191
211
|
|
|
192
212
|
#[wasm_bindgen(js_name=toObject)]
|
|
193
213
|
pub fn to_object(&self, skip_signature: Option<bool>) -> Result<JsValue, JsValue> {
|
|
194
|
-
let serde_object = self
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
214
|
+
let mut serde_object = self.0.to_object().map_err(from_protocol_error)?;
|
|
215
|
+
|
|
216
|
+
if skip_signature.unwrap_or(false) {
|
|
217
|
+
for path in
|
|
218
|
+
<DataContractUpdateTransition as StateTransitionFieldTypes>::signature_property_paths()
|
|
219
|
+
{
|
|
220
|
+
serde_object
|
|
221
|
+
.remove_values_matching_path(path)
|
|
222
|
+
.map_err(|e| from_protocol_error(ProtocolError::ValueError(e)))?;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
198
225
|
|
|
199
226
|
serde_object
|
|
200
227
|
.serialize(&serde_wasm_bindgen::Serializer::json_compatible())
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
use dpp::document::{
|
|
2
|
-
DocumentV0Getters, DocumentV0Setters, ExtendedDocument, EXTENDED_DOCUMENT_IDENTIFIER_FIELDS,
|
|
3
|
-
};
|
|
1
|
+
use dpp::document::{DocumentV0Getters, DocumentV0Setters, ExtendedDocument};
|
|
4
2
|
use serde_json::Value as JsonValue;
|
|
5
3
|
|
|
6
4
|
use dpp::platform_value::{Bytes32, Value};
|
|
7
5
|
use dpp::prelude::{Identifier, Revision, TimestampMillis};
|
|
8
6
|
|
|
9
|
-
use dpp::util::json_value::JsonValueExt;
|
|
10
|
-
|
|
11
7
|
use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
|
|
12
8
|
use dpp::document::serialization_traits::ExtendedDocumentPlatformConversionMethodsV0;
|
|
13
9
|
use dpp::platform_value::converter::serde_json::BTreeValueJsonConverter;
|
|
@@ -21,14 +17,12 @@ use crate::buffer::Buffer;
|
|
|
21
17
|
use crate::data_contract::DataContractWasm;
|
|
22
18
|
#[allow(deprecated)] // BinaryType is unused in unused code below
|
|
23
19
|
use crate::document::BinaryType;
|
|
24
|
-
use crate::document::
|
|
20
|
+
use crate::document::DocumentWasm;
|
|
25
21
|
use crate::errors::RustConversionError;
|
|
26
22
|
use crate::identifier::{identifier_from_js_value, IdentifierWrapper};
|
|
27
|
-
use crate::lodash::lodash_set;
|
|
28
23
|
use crate::metadata::MetadataWasm;
|
|
29
24
|
use crate::utils::{with_serde_to_platform_value, IntoWasm, ToSerdeJSONExt, WithJsError};
|
|
30
25
|
use crate::validation::ValidationResultWasm;
|
|
31
|
-
use crate::with_js_error;
|
|
32
26
|
|
|
33
27
|
#[wasm_bindgen(js_name=ExtendedDocument)]
|
|
34
28
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
@@ -187,6 +181,21 @@ impl ExtendedDocumentWasm {
|
|
|
187
181
|
Ok(js_value)
|
|
188
182
|
}
|
|
189
183
|
|
|
184
|
+
#[wasm_bindgen(js_name=toObject)]
|
|
185
|
+
pub fn to_object(&self) -> Result<JsValue, JsValue> {
|
|
186
|
+
// Canonical object shape: every `$`-prefixed system field (id, ownerId,
|
|
187
|
+
// type, dataContractId, revision, timestamps/block-heights, creatorId)
|
|
188
|
+
// plus the flattened document properties, with identifiers and binary
|
|
189
|
+
// data rendered as `Uint8Array`. Serializing the non-human-readable
|
|
190
|
+
// `to_map_value()` turns every identifier/bytes node — including nested
|
|
191
|
+
// document properties — into a `Uint8Array` in one pass, so there is no
|
|
192
|
+
// need to walk the document type's identifier/binary paths.
|
|
193
|
+
let map = self.0.to_map_value().with_js_error()?;
|
|
194
|
+
let serializer =
|
|
195
|
+
serde_wasm_bindgen::Serializer::json_compatible().serialize_bytes_as_arrays(false);
|
|
196
|
+
Ok(map.serialize(&serializer)?)
|
|
197
|
+
}
|
|
198
|
+
|
|
190
199
|
#[wasm_bindgen(js_name=set)]
|
|
191
200
|
pub fn set(&mut self, path: String, js_value_to_set: JsValue) -> Result<(), JsValue> {
|
|
192
201
|
let value: Value = js_value_to_set.with_serde_to_platform_value()?;
|
|
@@ -273,58 +282,6 @@ impl ExtendedDocumentWasm {
|
|
|
273
282
|
Ok(())
|
|
274
283
|
}
|
|
275
284
|
|
|
276
|
-
#[wasm_bindgen(js_name=toObject)]
|
|
277
|
-
pub fn to_object(&self, options: &JsValue) -> Result<JsValue, JsValue> {
|
|
278
|
-
let options: ConversionOptions = if !options.is_undefined() && options.is_object() {
|
|
279
|
-
let raw_options = options.with_serde_to_json_value()?;
|
|
280
|
-
serde_json::from_value(raw_options).with_js_error()?
|
|
281
|
-
} else {
|
|
282
|
-
Default::default()
|
|
283
|
-
};
|
|
284
|
-
let mut value = self.0.to_json_object_for_validation().with_js_error()?;
|
|
285
|
-
|
|
286
|
-
let document_type = self.0.document_type().with_js_error()?;
|
|
287
|
-
|
|
288
|
-
let identifier_paths = document_type.identifier_paths();
|
|
289
|
-
let binary_paths = document_type.binary_paths();
|
|
290
|
-
|
|
291
|
-
let serializer = serde_wasm_bindgen::Serializer::json_compatible();
|
|
292
|
-
let js_value = value.serialize(&serializer)?;
|
|
293
|
-
|
|
294
|
-
for path in identifier_paths
|
|
295
|
-
.iter()
|
|
296
|
-
.map(|s| s.as_str())
|
|
297
|
-
.chain(EXTENDED_DOCUMENT_IDENTIFIER_FIELDS)
|
|
298
|
-
{
|
|
299
|
-
if let Ok(bytes) = value.remove_value_at_path_into::<Vec<u8>>(path) {
|
|
300
|
-
let buffer = Buffer::from_bytes_owned(bytes);
|
|
301
|
-
if !options.skip_identifiers_conversion {
|
|
302
|
-
lodash_set(&js_value, path, buffer.into());
|
|
303
|
-
} else {
|
|
304
|
-
let id = IdentifierWrapper::new(buffer.into());
|
|
305
|
-
lodash_set(&js_value, path, id.into());
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
for path in binary_paths {
|
|
311
|
-
if let Ok(bytes) = value.remove_value_at_path_into::<Vec<u8>>(path) {
|
|
312
|
-
let buffer = Buffer::from_bytes(&bytes);
|
|
313
|
-
lodash_set(&js_value, path, buffer.into());
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
Ok(js_value)
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
#[wasm_bindgen(js_name=toJSON)]
|
|
321
|
-
pub fn to_json(&self) -> Result<JsValue, JsValue> {
|
|
322
|
-
let value = self.0.to_json(PlatformVersion::first()).with_js_error()?;
|
|
323
|
-
let serializer = serde_wasm_bindgen::Serializer::json_compatible();
|
|
324
|
-
|
|
325
|
-
with_js_error!(value.serialize(&serializer))
|
|
326
|
-
}
|
|
327
|
-
|
|
328
285
|
#[wasm_bindgen(js_name=toBuffer)]
|
|
329
286
|
pub fn to_buffer(&self) -> Result<Buffer, JsValue> {
|
|
330
287
|
let bytes: Vec<u8> = self
|
package/src/document/mod.rs
CHANGED
|
@@ -11,7 +11,9 @@ use crate::data_contract::DataContractWasm;
|
|
|
11
11
|
use crate::identifier::IdentifierWrapper;
|
|
12
12
|
|
|
13
13
|
use crate::utils::WithJsError;
|
|
14
|
-
use crate::utils::{
|
|
14
|
+
use crate::utils::{
|
|
15
|
+
json_value_to_platform_value_lenient, with_serde_to_json_value, ToSerdeJSONExt,
|
|
16
|
+
};
|
|
15
17
|
|
|
16
18
|
use dpp::document::document_methods::DocumentMethodsV0;
|
|
17
19
|
use dpp::document::DocumentV0Getters;
|
|
@@ -39,7 +41,6 @@ use dpp::{platform_value, ProtocolError};
|
|
|
39
41
|
|
|
40
42
|
use dpp::data_contract::accessors::v0::DataContractV0Getters;
|
|
41
43
|
use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
|
|
42
|
-
use dpp::document::serialization_traits::DocumentPlatformValueMethodsV0;
|
|
43
44
|
use dpp::version::PlatformVersion;
|
|
44
45
|
use serde_json::Value as JsonValue;
|
|
45
46
|
|
|
@@ -71,7 +72,8 @@ impl DocumentWasm {
|
|
|
71
72
|
js_data_contract: &DataContractWasm,
|
|
72
73
|
js_document_type_name: JsValue,
|
|
73
74
|
) -> Result<DocumentWasm, JsValue> {
|
|
74
|
-
let mut raw_document: Value =
|
|
75
|
+
let mut raw_document: Value =
|
|
76
|
+
json_value_to_platform_value_lenient(with_serde_to_json_value(&js_raw_document)?);
|
|
75
77
|
|
|
76
78
|
let document_type_name = js_document_type_name
|
|
77
79
|
.as_string()
|
|
@@ -99,8 +101,23 @@ impl DocumentWasm {
|
|
|
99
101
|
.with_js_error()?;
|
|
100
102
|
// The binary paths are not being converted, because they always should be a `Buffer`. `Buffer` is always an Array
|
|
101
103
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
// Phase D step 8 slice B replaced legacy `Document::from_platform_value`
|
|
105
|
+
// with canonical `ValueConvertible::from_object`, which requires a
|
|
106
|
+
// `$formatVersion` tag. Insert it for un-tagged JS-supplied input
|
|
107
|
+
// before delegating.
|
|
108
|
+
if let Value::Map(ref mut entries) = raw_document {
|
|
109
|
+
let has_tag = entries
|
|
110
|
+
.iter()
|
|
111
|
+
.any(|(k, _)| matches!(k, Value::Text(s) if s == "$formatVersion"));
|
|
112
|
+
if !has_tag {
|
|
113
|
+
entries.push((
|
|
114
|
+
Value::Text("$formatVersion".to_string()),
|
|
115
|
+
Value::Text("0".to_string()),
|
|
116
|
+
));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
use dpp::serialization::ValueConvertible;
|
|
120
|
+
let document = Document::from_object(raw_document).with_js_error()?;
|
|
104
121
|
|
|
105
122
|
Ok(document.into())
|
|
106
123
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
use dpp::dashcore::consensus::Encodable;
|
|
2
2
|
use dpp::dashcore::OutPoint;
|
|
3
3
|
use dpp::identity::state_transition::asset_lock_proof::AssetLockProofType;
|
|
4
|
+
use dpp::serialization::ValueConvertible;
|
|
4
5
|
use serde::{Deserialize, Serialize};
|
|
5
6
|
use std::convert::TryInto;
|
|
6
7
|
use wasm_bindgen::prelude::*;
|
|
@@ -117,7 +118,9 @@ impl ChainAssetLockProofWasm {
|
|
|
117
118
|
|
|
118
119
|
#[wasm_bindgen(js_name=toObject)]
|
|
119
120
|
pub fn to_object(&self) -> Result<JsValue, JsValue> {
|
|
120
|
-
|
|
121
|
+
// `to_cleaned_object` was a pure delegation to `to_object` in rs-dpp;
|
|
122
|
+
// the canonical `ValueConvertible::to_object` produces the same Value.
|
|
123
|
+
let asset_lock_value = self.0.to_object().with_js_error()?;
|
|
121
124
|
|
|
122
125
|
let serializer = serde_wasm_bindgen::Serializer::json_compatible();
|
|
123
126
|
let js_object = with_js_error!(asset_lock_value.serialize(&serializer))?;
|
|
@@ -5,6 +5,7 @@ use dpp::dashcore::{
|
|
|
5
5
|
|
|
6
6
|
use dpp::dashcore::consensus::Encodable;
|
|
7
7
|
use dpp::identity::state_transition::asset_lock_proof::AssetLockProofType;
|
|
8
|
+
use dpp::serialization::ValueConvertible;
|
|
8
9
|
use serde::{Deserialize, Serialize};
|
|
9
10
|
use std::convert::TryInto;
|
|
10
11
|
use wasm_bindgen::prelude::*;
|
|
@@ -117,7 +118,10 @@ impl InstantAssetLockProofWasm {
|
|
|
117
118
|
|
|
118
119
|
#[wasm_bindgen(js_name=toObject)]
|
|
119
120
|
pub fn to_object(&self) -> Result<JsValue, JsValue> {
|
|
120
|
-
|
|
121
|
+
// `to_cleaned_object` was a pure delegation to `to_object` in
|
|
122
|
+
// rs-dpp; the canonical `ValueConvertible::to_object` produces the
|
|
123
|
+
// same Value (no `disabledAt` field on InstantAssetLockProof to clean).
|
|
124
|
+
let asset_lock_value = self.0.to_object().with_js_error()?;
|
|
121
125
|
|
|
122
126
|
let serializer = serde_wasm_bindgen::Serializer::json_compatible();
|
|
123
127
|
let js_object = with_js_error!(asset_lock_value.serialize(&serializer))?;
|
package/src/utils.rs
CHANGED
|
@@ -105,7 +105,57 @@ pub fn with_serde_to_json_value(data: &JsValue) -> Result<JsonValue, JsValue> {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
pub fn with_serde_to_platform_value(data: &JsValue) -> Result<Value, JsValue> {
|
|
108
|
-
Ok(
|
|
108
|
+
Ok(json_value_to_platform_value_lenient(
|
|
109
|
+
with_serde_to_json_value(data)?,
|
|
110
|
+
))
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/// Converts a `serde_json::Value` into a `platform_value::Value`, restoring the
|
|
114
|
+
/// legacy "array of u8 → `Value::Bytes`" coercion that `From<JsonValue> for Value`
|
|
115
|
+
/// used to perform before the Critical-2 faithful-conversion change in
|
|
116
|
+
/// rs-platform-value.
|
|
117
|
+
///
|
|
118
|
+
/// The JS boundary of this (deprecated) crate stringifies JS `Buffer`s into plain
|
|
119
|
+
/// number arrays via [`stringify`], then relied on that coercion to reconstruct
|
|
120
|
+
/// binary document fields (`byteArrayField`, identifiers, …) as `Value::Bytes`.
|
|
121
|
+
/// rs-platform-value is now intentionally faithful (array → `Value::Array`), so we
|
|
122
|
+
/// re-apply the heuristic here — scoped to the legacy crate's JS input only —
|
|
123
|
+
/// rather than reintroduce the footgun globally.
|
|
124
|
+
pub(crate) fn json_value_to_platform_value_lenient(value: JsonValue) -> Value {
|
|
125
|
+
match value {
|
|
126
|
+
JsonValue::Array(array) => {
|
|
127
|
+
let u8_max = u8::MAX as u64;
|
|
128
|
+
// Matches the pre-Critical-2 heuristic exactly: length >= 10 and every
|
|
129
|
+
// element a u64 that fits in a byte ⇒ treat as a byte array.
|
|
130
|
+
if array.len() >= 10
|
|
131
|
+
&& array
|
|
132
|
+
.iter()
|
|
133
|
+
.all(|v| v.as_u64().map(|int| int <= u8_max).unwrap_or(false))
|
|
134
|
+
{
|
|
135
|
+
Value::Bytes(
|
|
136
|
+
array
|
|
137
|
+
.into_iter()
|
|
138
|
+
.map(|v| v.as_u64().expect("checked above") as u8)
|
|
139
|
+
.collect(),
|
|
140
|
+
)
|
|
141
|
+
} else {
|
|
142
|
+
Value::Array(
|
|
143
|
+
array
|
|
144
|
+
.into_iter()
|
|
145
|
+
.map(json_value_to_platform_value_lenient)
|
|
146
|
+
.collect(),
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
JsonValue::Object(map) => Value::Map(
|
|
151
|
+
map.into_iter()
|
|
152
|
+
.map(|(k, v)| (k.into(), json_value_to_platform_value_lenient(v)))
|
|
153
|
+
.collect(),
|
|
154
|
+
),
|
|
155
|
+
// Null / Bool / Number / String are unaffected by the heuristic and convert
|
|
156
|
+
// identically through the canonical impl.
|
|
157
|
+
other => other.into(),
|
|
158
|
+
}
|
|
109
159
|
}
|
|
110
160
|
|
|
111
161
|
pub fn with_serde_into<D>(data: &JsValue) -> Result<D, JsValue>
|
|
@@ -32,66 +32,6 @@ describe('ExtendedDocument', () => {
|
|
|
32
32
|
document.setMetadata(metadataFixture);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
describe.skip('#toJSON', () => {
|
|
36
|
-
it('should return json document - Rust', () => {
|
|
37
|
-
const result = document.toJSON();
|
|
38
|
-
|
|
39
|
-
expect(result).to.deep.equal({
|
|
40
|
-
$protocolVersion: document.getProtocolVersion(),
|
|
41
|
-
$dataContractId: dataContract.getId().toString(),
|
|
42
|
-
$id: document.getId().toString(),
|
|
43
|
-
$ownerId: document.getOwnerId().toString(),
|
|
44
|
-
$revision: 1,
|
|
45
|
-
$type: 'withByteArrays',
|
|
46
|
-
byteArrayField: document.get('byteArrayField').toString('base64'),
|
|
47
|
-
identifierField: document.get('identifierField').toString(),
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe('#toObject', () => {
|
|
53
|
-
it('should return raw document - Rust', () => {
|
|
54
|
-
const result = document.toObject();
|
|
55
|
-
|
|
56
|
-
expect(result).to.deep.equal({
|
|
57
|
-
$createdAt: null, // TODO: it should be omitted
|
|
58
|
-
$createdAtBlockHeight: null,
|
|
59
|
-
$createdAtCoreBlockHeight: null,
|
|
60
|
-
$creatorId: null,
|
|
61
|
-
$updatedAt: null,
|
|
62
|
-
$updatedAtBlockHeight: null,
|
|
63
|
-
$updatedAtCoreBlockHeight: null,
|
|
64
|
-
$transferredAt: null,
|
|
65
|
-
$transferredAtBlockHeight: null,
|
|
66
|
-
$transferredAtCoreBlockHeight: null,
|
|
67
|
-
$dataContractId: dataContract.getId().toBuffer(),
|
|
68
|
-
$id: document.getId().toBuffer(),
|
|
69
|
-
$ownerId: document.getOwnerId().toBuffer(),
|
|
70
|
-
$revision: 1,
|
|
71
|
-
$type: 'withByteArrays',
|
|
72
|
-
byteArrayField: document.get('byteArrayField'),
|
|
73
|
-
identifierField: document.get('identifierField').toBuffer(),
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should return raw document with Identifiers - Rust', () => {
|
|
78
|
-
const result = document.toObject({ skipIdentifiersConversion: true });
|
|
79
|
-
|
|
80
|
-
expect(result.$dataContractId).to.be.an.instanceOf(Identifier);
|
|
81
|
-
expect(result.$id).to.be.an.instanceOf(Identifier);
|
|
82
|
-
expect(result.$ownerId).to.be.an.instanceOf(Identifier);
|
|
83
|
-
expect(result.identifierField).to.be.an.instanceOf(Identifier);
|
|
84
|
-
|
|
85
|
-
expect(result.$dataContractId.toBuffer()).to.deep.equal(dataContract.getId().toBuffer());
|
|
86
|
-
expect(result.$id.toBuffer()).to.deep.equal(document.getId().toBuffer());
|
|
87
|
-
expect(result.$ownerId.toBuffer()).to.deep.equal(document.getOwnerId().toBuffer());
|
|
88
|
-
expect(result.identifierField.toBuffer()).to.deep.equal(document.get('identifierField').toBuffer());
|
|
89
|
-
expect(BigInt(result.$revision)).to.deep.equal(document.getRevision());
|
|
90
|
-
expect(result.$type).to.deep.equal(document.getType());
|
|
91
|
-
expect(result.byteArrayField).to.deep.equal(document.get('byteArrayField'));
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
35
|
describe('#setMetadata', () => {
|
|
96
36
|
it('should set metadata - Rust', () => {
|
|
97
37
|
const otherMetadata = new Metadata(BigInt(43), 1, BigInt(100), 2);
|
|
@@ -218,7 +218,7 @@ describe('DataContract', () => {
|
|
|
218
218
|
const result = dataContract.toJSON();
|
|
219
219
|
|
|
220
220
|
expect(result).to.deep.equal({
|
|
221
|
-
$formatVersion: '
|
|
221
|
+
$formatVersion: '1',
|
|
222
222
|
config: {
|
|
223
223
|
$formatVersion: '0',
|
|
224
224
|
canBeDeleted: false,
|
|
@@ -235,6 +235,16 @@ describe('DataContract', () => {
|
|
|
235
235
|
ownerId: bs58.encode(ownerId),
|
|
236
236
|
schemaDefs: null,
|
|
237
237
|
documentSchemas,
|
|
238
|
+
createdAt: null,
|
|
239
|
+
updatedAt: null,
|
|
240
|
+
createdAtBlockHeight: null,
|
|
241
|
+
updatedAtBlockHeight: null,
|
|
242
|
+
createdAtEpoch: null,
|
|
243
|
+
updatedAtEpoch: null,
|
|
244
|
+
description: null,
|
|
245
|
+
keywords: [],
|
|
246
|
+
groups: {},
|
|
247
|
+
tokens: {},
|
|
238
248
|
});
|
|
239
249
|
});
|
|
240
250
|
|
|
@@ -248,7 +258,7 @@ describe('DataContract', () => {
|
|
|
248
258
|
const result = dataContract.toJSON();
|
|
249
259
|
|
|
250
260
|
expect(result).to.deep.equal({
|
|
251
|
-
$formatVersion: '
|
|
261
|
+
$formatVersion: '1',
|
|
252
262
|
config: {
|
|
253
263
|
$formatVersion: '0',
|
|
254
264
|
canBeDeleted: false,
|
|
@@ -265,6 +275,16 @@ describe('DataContract', () => {
|
|
|
265
275
|
ownerId: bs58.encode(ownerId),
|
|
266
276
|
documentSchemas,
|
|
267
277
|
schemaDefs: $defs,
|
|
278
|
+
createdAt: null,
|
|
279
|
+
updatedAt: null,
|
|
280
|
+
createdAtBlockHeight: null,
|
|
281
|
+
updatedAtBlockHeight: null,
|
|
282
|
+
createdAtEpoch: null,
|
|
283
|
+
updatedAtEpoch: null,
|
|
284
|
+
description: null,
|
|
285
|
+
keywords: [],
|
|
286
|
+
groups: {},
|
|
287
|
+
tokens: {},
|
|
268
288
|
});
|
|
269
289
|
});
|
|
270
290
|
});
|
|
@@ -72,7 +72,7 @@ describe('DataContractCreateTransition', () => {
|
|
|
72
72
|
it('should return serialized State Transition', () => {
|
|
73
73
|
const result = stateTransition.toBuffer();
|
|
74
74
|
expect(result).to.be.instanceOf(Buffer);
|
|
75
|
-
expect(result).to.have.lengthOf(
|
|
75
|
+
expect(result).to.have.lengthOf(2370);
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
it('should be able to restore contract config from bytes', () => {
|
|
@@ -20,7 +20,8 @@ describe('DataContractUpdateTransition', () => {
|
|
|
20
20
|
stateTransition = new DataContractUpdateTransition({
|
|
21
21
|
protocolVersion: 1,
|
|
22
22
|
dataContract: dataContract.toObject(),
|
|
23
|
-
|
|
23
|
+
// Canonical serde wire name for the identity-contract-nonce field.
|
|
24
|
+
'$identity-contract-nonce': 1,
|
|
24
25
|
});
|
|
25
26
|
});
|
|
26
27
|
|
|
@@ -65,7 +66,7 @@ describe('DataContractUpdateTransition', () => {
|
|
|
65
66
|
it('should return serialized State Transition', () => {
|
|
66
67
|
const result = stateTransition.toBuffer();
|
|
67
68
|
expect(result).to.be.instanceOf(Buffer);
|
|
68
|
-
expect(result).to.have.lengthOf(
|
|
69
|
+
expect(result).to.have.lengthOf(2370);
|
|
69
70
|
});
|
|
70
71
|
|
|
71
72
|
it('should be able to restore contract config from bytes', () => {
|
|
@@ -397,28 +397,6 @@ describe('Document', () => {
|
|
|
397
397
|
});
|
|
398
398
|
});
|
|
399
399
|
|
|
400
|
-
describe('#toJSON', () => {
|
|
401
|
-
it('should return Document as plain JS object', () => {
|
|
402
|
-
const jsonDocument = {
|
|
403
|
-
...rawDocument,
|
|
404
|
-
$dataContractId: document.getDataContractId().toString(),
|
|
405
|
-
$dataContract: document.getDataContract().toJSON(),
|
|
406
|
-
$id: document.getId().toString(),
|
|
407
|
-
$ownerId: document.getOwnerId().toString(),
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
expect(document.toJSON()).to.deep.equal(jsonDocument);
|
|
411
|
-
});
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
describe('#toObject', () => {
|
|
415
|
-
it('should return Document as object', () => {
|
|
416
|
-
const result = document.toObject();
|
|
417
|
-
|
|
418
|
-
expect(rawDocumentWithBuffers).to.deep.equal(result);
|
|
419
|
-
});
|
|
420
|
-
});
|
|
421
|
-
|
|
422
400
|
describe('#toBuffer', () => {
|
|
423
401
|
it('should return serialized Document', () => {
|
|
424
402
|
const buffer = document.toBuffer();
|