dpp/identity/conversion/platform_value/
mod.rs1mod v0;
2
3use crate::identity::{Identity, IdentityV0};
4use crate::version::PlatformVersion;
5use crate::ProtocolError;
6use platform_value::Value;
7use platform_version::TryFromPlatformVersioned;
8pub use v0::IdentityPlatformValueConversionMethodsV0;
9
10impl IdentityPlatformValueConversionMethodsV0 for Identity {}
11
12impl TryFromPlatformVersioned<Value> for Identity {
13 type Error = ProtocolError;
14
15 fn try_from_platform_versioned(
16 value: Value,
17 platform_version: &PlatformVersion,
18 ) -> Result<Self, Self::Error> {
19 match platform_version
20 .dpp
21 .identity_versions
22 .identity_structure_version
23 {
24 0 => {
25 let identity_v0: IdentityV0 =
26 platform_value::from_value(value).map_err(ProtocolError::ValueError)?;
27 Ok(identity_v0.into())
28 }
29 version => Err(ProtocolError::UnknownVersionMismatch {
30 method: "Identity::try_from_owned_value".to_string(),
31 known_versions: vec![0],
32 received: version,
33 }),
34 }
35 }
36}
37
38impl TryFromPlatformVersioned<&Value> for Identity {
39 type Error = ProtocolError;
40
41 fn try_from_platform_versioned(
42 value: &Value,
43 platform_version: &PlatformVersion,
44 ) -> Result<Self, Self::Error> {
45 match platform_version
46 .dpp
47 .identity_versions
48 .identity_structure_version
49 {
50 0 => {
51 let identity_v0: IdentityV0 =
52 platform_value::from_value(value.clone()).map_err(ProtocolError::ValueError)?;
53 Ok(identity_v0.into())
54 }
55 version => Err(ProtocolError::UnknownVersionMismatch {
56 method: "Identity::try_from_owned_value".to_string(),
57 known_versions: vec![0],
58 received: version,
59 }),
60 }
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use crate::identity::accessors::IdentityGettersV0;
68 use crate::identity::identity_public_key::v0::IdentityPublicKeyV0;
69 use crate::identity::IdentityPublicKey;
70 use crate::identity::{KeyType, Purpose, SecurityLevel};
71 use crate::serialization::ValueConvertible;
72 use platform_value::{platform_value, BinaryData, Identifier};
73 use platform_version::version::LATEST_PLATFORM_VERSION;
74 use std::collections::BTreeMap;
75
76 fn sample_identity_v0() -> IdentityV0 {
77 let mut keys: BTreeMap<u32, IdentityPublicKey> = BTreeMap::new();
78 keys.insert(
79 0,
80 IdentityPublicKey::V0(IdentityPublicKeyV0 {
81 id: 0,
82 purpose: Purpose::AUTHENTICATION,
83 security_level: SecurityLevel::MASTER,
84 contract_bounds: None,
85 key_type: KeyType::ECDSA_SECP256K1,
86 read_only: false,
87 data: BinaryData::new(vec![0x01; 33]),
88 disabled_at: None,
89 }),
90 );
91 IdentityV0 {
92 id: Identifier::from([42u8; 32]),
93 public_keys: keys,
94 balance: 7,
95 revision: 2,
96 }
97 }
98
99 fn tagged_raw_value() -> Value {
115 use platform_value::string_encoding::{encode, Encoding};
116 let data_b64 = encode(&[0x22u8; 33], Encoding::Base64);
117 platform_value!({
118 "id": Identifier::from([7u8; 32]),
119 "publicKeys": [
120 {
121 "$formatVersion": "0",
122 "id": 0u32,
123 "type": 0u8,
124 "purpose": 0u8,
125 "securityLevel": 0u8,
126 "contractBounds": Value::Null,
127 "data": data_b64,
128 "readOnly": false,
129 "disabledAt": Value::Null,
130 }
131 ],
132 "balance": 100u64,
133 "revision": 1u64,
134 })
135 }
136
137 #[test]
138 fn try_from_platform_versioned_owned_value_parses_legacy_shape() {
139 let value = tagged_raw_value();
140 let identity = Identity::try_from_platform_versioned(value, LATEST_PLATFORM_VERSION)
141 .expect("should parse legacy raw object");
142 assert_eq!(identity.balance(), 100);
143 assert_eq!(identity.revision(), 1);
144 assert_eq!(identity.public_keys().len(), 1);
145 }
146
147 #[test]
148 fn try_from_platform_versioned_ref_value_parses_legacy_shape() {
149 let value = tagged_raw_value();
150 let identity = Identity::try_from_platform_versioned(&value, LATEST_PLATFORM_VERSION)
151 .expect("should parse legacy raw object from &Value");
152 assert_eq!(identity.balance(), 100);
153 }
154
155 #[test]
156 fn try_from_platform_versioned_errors_on_garbage_owned() {
157 let value = Value::Null;
158 let result = Identity::try_from_platform_versioned(value, LATEST_PLATFORM_VERSION);
159 assert!(matches!(result, Err(ProtocolError::ValueError(_))));
160 }
161
162 #[test]
163 fn try_from_platform_versioned_errors_on_garbage_ref() {
164 let value = Value::Text("not a map".to_string());
165 let result = Identity::try_from_platform_versioned(&value, LATEST_PLATFORM_VERSION);
166 assert!(matches!(result, Err(ProtocolError::ValueError(_))));
167 }
168
169 #[test]
174 fn identity_wrapper_to_cleaned_object_includes_format_version_tag() {
175 let identity: Identity = sample_identity_v0().into();
176 let value = identity.to_cleaned_object().expect("to_cleaned_object");
177 let map = value.to_map_ref().expect("map");
178 assert!(
179 map.iter()
180 .any(|(k, _)| k.as_text() == Some("$formatVersion")),
181 "Identity enum wrapper must keep its format version tag"
182 );
183 }
184
185 #[test]
186 fn identity_wrapper_to_object_differs_from_v0_inner_shape() {
187 let v0 = sample_identity_v0();
190 let wrapper: Identity = v0.clone().into();
191 let inner_value = v0.to_object().unwrap();
192 let outer_value = wrapper.to_object().unwrap();
193 assert_ne!(inner_value, outer_value);
194 }
195}