@dashevo/dapi-grpc 0.25.22 → 1.0.0-beta.1
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 +35 -16
- package/build.rs +139 -56
- package/clients/core/v0/nodejs/CorePromiseClient.js +124 -13
- package/clients/core/v0/nodejs/core_pbjs.js +1922 -987
- package/clients/core/v0/nodejs/core_protoc.js +1291 -645
- package/clients/core/v0/rust/core_example.rs +1 -1
- package/clients/core/v0/web/CorePromiseClient.js +49 -5
- package/clients/core/v0/web/core_pb.d.ts +173 -89
- package/clients/core/v0/web/core_pb.js +1291 -645
- package/clients/core/v0/web/core_pb_service.d.ts +59 -10
- package/clients/core/v0/web/core_pb_service.js +134 -6
- package/clients/platform/v0/nodejs/PlatformPromiseClient.js +208 -14
- package/clients/platform/v0/nodejs/platform_pbjs.js +22951 -9938
- package/clients/platform/v0/nodejs/platform_protoc.js +22332 -9091
- package/clients/platform/v0/rust/platform_example.rs +1 -1
- package/clients/platform/v0/web/PlatformPromiseClient.js +64 -8
- package/clients/platform/v0/web/platform_pb.d.ts +2057 -302
- package/clients/platform/v0/web/platform_pb.js +22332 -9091
- package/clients/platform/v0/web/platform_pb_service.d.ts +187 -35
- package/clients/platform/v0/web/platform_pb_service.js +355 -35
- package/package.json +2 -2
- package/protos/core/v0/core.proto +45 -23
- package/protos/platform/v0/platform.proto +429 -50
- package/src/lib.rs +26 -2
- package/src/mock/serde_mockable.rs +105 -0
- package/src/mock.rs +130 -0
- package/test/unit/clients/core/v0/nodejs/CorePromiseClient.spec.js +27 -6
- package/test/unit/clients/platform/v0/nodejs/PlatformPromiseClient.spec.js +55 -1
- package/test/unit/getCoreDefinition.spec.js +5 -2
- package/src/core/proto/org.dash.platform.dapi.v0.rs +0 -666
- package/src/platform/proto/org.dash.platform.dapi.v0.rs +0 -2481
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
//! Serde serialization and deserialization for Mockable objects.
|
|
2
|
+
//!
|
|
3
|
+
//! This module provides a custom serialization and deserialization implementation for Mockable objects.
|
|
4
|
+
//!
|
|
5
|
+
//! /// ## Example
|
|
6
|
+
///
|
|
7
|
+
/// ```rust
|
|
8
|
+
/// struct SomeObject {
|
|
9
|
+
/// field: u32,
|
|
10
|
+
/// }
|
|
11
|
+
///
|
|
12
|
+
/// impl dapi_grpc::mock::Mockable for SomeObject {
|
|
13
|
+
/// fn mock_serialize(&self) -> Option<Vec<u8>> {
|
|
14
|
+
/// Some(self.field.to_be_bytes().to_vec())
|
|
15
|
+
/// }
|
|
16
|
+
///
|
|
17
|
+
/// fn mock_deserialize(bytes: &[u8]) -> Option<Self> {
|
|
18
|
+
/// if bytes.len() != 4 {
|
|
19
|
+
/// return None;
|
|
20
|
+
/// }
|
|
21
|
+
///
|
|
22
|
+
/// Some(SomeObject {
|
|
23
|
+
/// field: u32::from_be_bytes(bytes.try_into().expect("4 bytes")),
|
|
24
|
+
/// })
|
|
25
|
+
/// }
|
|
26
|
+
/// }
|
|
27
|
+
///
|
|
28
|
+
/// #[derive(serde::Serialize,serde::Deserialize)]
|
|
29
|
+
/// struct TestStruct {
|
|
30
|
+
/// #[serde(with="dapi_grpc::mock::serde_mockable")]
|
|
31
|
+
/// field: SomeObject,
|
|
32
|
+
/// }
|
|
33
|
+
/// ```
|
|
34
|
+
use super::Mockable;
|
|
35
|
+
|
|
36
|
+
use serde::{
|
|
37
|
+
de::{self, Visitor},
|
|
38
|
+
Deserializer, Serializer,
|
|
39
|
+
};
|
|
40
|
+
use serde_bytes::Deserialize;
|
|
41
|
+
use std::fmt;
|
|
42
|
+
use std::marker::PhantomData;
|
|
43
|
+
|
|
44
|
+
/// Serialize any Mockable object to bytes.
|
|
45
|
+
///
|
|
46
|
+
/// ## Example
|
|
47
|
+
///
|
|
48
|
+
/// `#[serde(with="dapi_grpc::mock::serde_mockable")]`
|
|
49
|
+
pub fn serialize<T: Mockable, S>(data: &T, serializer: S) -> Result<S::Ok, S::Error>
|
|
50
|
+
where
|
|
51
|
+
S: Serializer,
|
|
52
|
+
{
|
|
53
|
+
match data.mock_serialize() {
|
|
54
|
+
Some(bytes) => serializer.serialize_bytes(bytes.as_slice()),
|
|
55
|
+
None => Err(serde::ser::Error::custom(
|
|
56
|
+
"Mockable object is not serializable",
|
|
57
|
+
)),
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
struct MockableVisitor<T> {
|
|
62
|
+
marker: PhantomData<T>,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
impl<'de, T> Visitor<'de> for MockableVisitor<T>
|
|
66
|
+
where
|
|
67
|
+
T: Mockable,
|
|
68
|
+
{
|
|
69
|
+
type Value = T;
|
|
70
|
+
|
|
71
|
+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
72
|
+
formatter.write_str("a byte array")
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
|
76
|
+
where
|
|
77
|
+
E: de::Error,
|
|
78
|
+
{
|
|
79
|
+
T::mock_deserialize(v).ok_or_else(|| E::custom("Failed to deserialize Mockable object"))
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
|
|
83
|
+
where
|
|
84
|
+
A: de::SeqAccess<'de>,
|
|
85
|
+
{
|
|
86
|
+
let bytes = <Vec<u8>>::deserialize(de::value::SeqAccessDeserializer::new(seq))?;
|
|
87
|
+
T::mock_deserialize(&bytes).ok_or_else(|| {
|
|
88
|
+
serde::de::Error::custom("Failed to deserialize Mockable object from seq")
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// Deserialize any Mockable object from bytes.
|
|
94
|
+
///
|
|
95
|
+
/// ## Example
|
|
96
|
+
///
|
|
97
|
+
/// `#[serde(with="dapi_grpc::mock::serde_mockable")]`
|
|
98
|
+
pub fn deserialize<'de, T: Mockable, D>(deserializer: D) -> Result<T, D::Error>
|
|
99
|
+
where
|
|
100
|
+
D: Deserializer<'de>,
|
|
101
|
+
{
|
|
102
|
+
deserializer.deserialize_bytes(MockableVisitor {
|
|
103
|
+
marker: PhantomData,
|
|
104
|
+
})
|
|
105
|
+
}
|
package/src/mock.rs
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
//! Mocking support for messages.
|
|
2
|
+
//!
|
|
3
|
+
//! Contains [Mockable] trait that should be implemented by any object that can be used in the DAPI.
|
|
4
|
+
//!
|
|
5
|
+
//! Note that this trait is defined even if mocks are not supported, but it should always return `None` on serialization.
|
|
6
|
+
|
|
7
|
+
#[cfg(feature = "mocks")]
|
|
8
|
+
pub mod serde_mockable;
|
|
9
|
+
|
|
10
|
+
use tonic::Streaming;
|
|
11
|
+
|
|
12
|
+
/// Mocking support for messages.
|
|
13
|
+
///
|
|
14
|
+
/// This trait should be implemented by any object that can be used in the DAPI.
|
|
15
|
+
///
|
|
16
|
+
/// We use serde_json to serialize/deserialize messages.
|
|
17
|
+
// TODO: Move to a different crate where it can be easily shared by dapi-grpc, dash-platform-sdk, and rs-dapi-client.
|
|
18
|
+
pub trait Mockable
|
|
19
|
+
where
|
|
20
|
+
Self: std::marker::Sized,
|
|
21
|
+
{
|
|
22
|
+
/// Serialize the message to bytes for mocking purposes.
|
|
23
|
+
///
|
|
24
|
+
/// Returns None if the message is not serializable or mocking is disabled.
|
|
25
|
+
///
|
|
26
|
+
/// # Panics
|
|
27
|
+
///
|
|
28
|
+
/// Panics on any error.
|
|
29
|
+
fn mock_serialize(&self) -> Option<Vec<u8>> {
|
|
30
|
+
None
|
|
31
|
+
}
|
|
32
|
+
/// Deserialize the message serialized with [mock_serialize()].
|
|
33
|
+
///
|
|
34
|
+
/// Returns None if the message is not serializable or mocking is disabled.
|
|
35
|
+
///
|
|
36
|
+
/// # Panics
|
|
37
|
+
///
|
|
38
|
+
/// Panics on any error.
|
|
39
|
+
fn mock_deserialize(_data: &[u8]) -> Option<Self> {
|
|
40
|
+
None
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
#[cfg(feature = "mocks")]
|
|
44
|
+
#[derive(serde::Serialize, serde::Deserialize)]
|
|
45
|
+
enum SerializableResult {
|
|
46
|
+
Ok(Vec<u8>),
|
|
47
|
+
Err(Vec<u8>),
|
|
48
|
+
}
|
|
49
|
+
impl<T, E> Mockable for Result<T, E>
|
|
50
|
+
where
|
|
51
|
+
T: Mockable,
|
|
52
|
+
E: Mockable,
|
|
53
|
+
{
|
|
54
|
+
#[cfg(feature = "mocks")]
|
|
55
|
+
fn mock_serialize(&self) -> Option<Vec<u8>> {
|
|
56
|
+
let serializable = match self {
|
|
57
|
+
Ok(value) => SerializableResult::Ok(value.mock_serialize()?),
|
|
58
|
+
Err(error) => SerializableResult::Err(error.mock_serialize()?),
|
|
59
|
+
};
|
|
60
|
+
serde_json::to_vec(&serializable).ok()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#[cfg(feature = "mocks")]
|
|
64
|
+
fn mock_deserialize(data: &[u8]) -> Option<Self> {
|
|
65
|
+
if data.is_empty() {
|
|
66
|
+
return None;
|
|
67
|
+
}
|
|
68
|
+
let deser: SerializableResult =
|
|
69
|
+
serde_json::from_slice(data).expect("unable to deserialize mock data");
|
|
70
|
+
Some(match deser {
|
|
71
|
+
SerializableResult::Ok(data) => Ok(T::mock_deserialize(&data)?),
|
|
72
|
+
SerializableResult::Err(data) => Err(E::mock_deserialize(&data)?),
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
impl<T: Mockable> Mockable for Option<T> {
|
|
78
|
+
#[cfg(feature = "mocks")]
|
|
79
|
+
fn mock_serialize(&self) -> Option<Vec<u8>> {
|
|
80
|
+
self.as_ref().and_then(|value| value.mock_serialize())
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#[cfg(feature = "mocks")]
|
|
84
|
+
fn mock_deserialize(data: &[u8]) -> Option<Self> {
|
|
85
|
+
T::mock_deserialize(data).map(Some)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
impl Mockable for Vec<u8> {
|
|
90
|
+
#[cfg(feature = "mocks")]
|
|
91
|
+
fn mock_serialize(&self) -> Option<Vec<u8>> {
|
|
92
|
+
serde_json::to_vec(self).ok()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#[cfg(feature = "mocks")]
|
|
96
|
+
fn mock_deserialize(data: &[u8]) -> Option<Self> {
|
|
97
|
+
serde_json::from_slice(data).ok()
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
#[cfg(feature = "mocks")]
|
|
101
|
+
#[derive(serde::Serialize, serde::Deserialize)]
|
|
102
|
+
struct MockableStatus {
|
|
103
|
+
code: i32,
|
|
104
|
+
message: Vec<u8>,
|
|
105
|
+
}
|
|
106
|
+
impl Mockable for crate::tonic::Status {
|
|
107
|
+
#[cfg(feature = "mocks")]
|
|
108
|
+
fn mock_serialize(&self) -> Option<Vec<u8>> {
|
|
109
|
+
let mockable = MockableStatus {
|
|
110
|
+
code: self.code().into(),
|
|
111
|
+
message: self.message().as_bytes().to_vec(),
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
Some(serde_json::to_vec(&mockable).expect("unable to serialize tonic::Status"))
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
#[cfg(feature = "mocks")]
|
|
118
|
+
fn mock_deserialize(data: &[u8]) -> Option<Self> {
|
|
119
|
+
let MockableStatus { code, message } =
|
|
120
|
+
serde_json::from_slice(data).expect("unable to deserialize tonic::Status");
|
|
121
|
+
let message = std::str::from_utf8(&message).expect("invalid utf8 message in tonic::Status");
|
|
122
|
+
Some(Self::new(code.into(), message))
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/// Mocking of gRPC streaming responses is not supported.
|
|
127
|
+
///
|
|
128
|
+
/// This will return `None` on serialization,
|
|
129
|
+
/// effectively disabling mocking of streaming responses.
|
|
130
|
+
impl<T: Mockable> Mockable for Streaming<T> {}
|
|
@@ -11,7 +11,8 @@ describe('CorePromiseClient', () => {
|
|
|
11
11
|
|
|
12
12
|
corePromiseClient = new CorePromiseClient('https://localhost/');
|
|
13
13
|
corePromiseClient.client = {
|
|
14
|
-
|
|
14
|
+
getBlockchainStatus: this.sinon.stub().resolves(response),
|
|
15
|
+
getMasternodeStatus: this.sinon.stub().resolves(response),
|
|
15
16
|
getBlock: this.sinon.stub().resolves(response),
|
|
16
17
|
broadcastTransaction: this.sinon.stub().resolves(response),
|
|
17
18
|
getTransaction: this.sinon.stub().resolves(response),
|
|
@@ -20,17 +21,37 @@ describe('CorePromiseClient', () => {
|
|
|
20
21
|
};
|
|
21
22
|
});
|
|
22
23
|
|
|
23
|
-
describe('#
|
|
24
|
-
it('should return status', async () => {
|
|
25
|
-
const result = await corePromiseClient.
|
|
24
|
+
describe('#getBlockchainStatus', () => {
|
|
25
|
+
it('should return core chain status', async () => {
|
|
26
|
+
const result = await corePromiseClient.getBlockchainStatus(request);
|
|
27
|
+
|
|
28
|
+
expect(result).to.equal(response);
|
|
29
|
+
expect(corePromiseClient.client.getBlockchainStatus).to.be.calledOnceWith(request);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should throw an error when metadata is not an object', async () => {
|
|
33
|
+
try {
|
|
34
|
+
corePromiseClient.getBlockchainStatus({}, 'metadata');
|
|
35
|
+
|
|
36
|
+
expect.fail('Error was not thrown');
|
|
37
|
+
} catch (e) {
|
|
38
|
+
expect(e.message).to.equal('metadata must be an object');
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('#getMasternodeStatus', () => {
|
|
44
|
+
it('should return masternode status', async () => {
|
|
45
|
+
const result = await corePromiseClient.getMasternodeStatus(request);
|
|
26
46
|
|
|
27
47
|
expect(result).to.equal(response);
|
|
28
|
-
expect(corePromiseClient.client.
|
|
48
|
+
expect(corePromiseClient.client.getMasternodeStatus)
|
|
49
|
+
.to.be.calledOnceWith(request);
|
|
29
50
|
});
|
|
30
51
|
|
|
31
52
|
it('should throw an error when metadata is not an object', async () => {
|
|
32
53
|
try {
|
|
33
|
-
corePromiseClient.
|
|
54
|
+
corePromiseClient.getMasternodeStatus({}, 'metadata');
|
|
34
55
|
|
|
35
56
|
expect.fail('Error was not thrown');
|
|
36
57
|
} catch (e) {
|
|
@@ -13,11 +13,15 @@ describe('PlatformPromiseClient', () => {
|
|
|
13
13
|
platformPromiseClient.client = {
|
|
14
14
|
broadcastStateTransition: this.sinon.stub().resolves(response),
|
|
15
15
|
getIdentity: this.sinon.stub().resolves(response),
|
|
16
|
+
getIdentitiesContractKeys: this.sinon.stub().resolves(response),
|
|
16
17
|
getDataContract: this.sinon.stub().resolves(response),
|
|
17
18
|
getDocuments: this.sinon.stub().resolves(response),
|
|
18
19
|
getEpochsInfo: this.sinon.stub().resolves(response),
|
|
19
20
|
getProtocolVersionUpgradeVoteStatus: this.sinon.stub().resolves(response),
|
|
20
21
|
getProtocolVersionUpgradeState: this.sinon.stub().resolves(response),
|
|
22
|
+
getIdentityContractNonce: this.sinon.stub().resolves(response),
|
|
23
|
+
getIdentityNonce: this.sinon.stub().resolves(response),
|
|
24
|
+
getIdentityKeys: this.sinon.stub().resolves(response),
|
|
21
25
|
};
|
|
22
26
|
});
|
|
23
27
|
|
|
@@ -60,6 +64,26 @@ describe('PlatformPromiseClient', () => {
|
|
|
60
64
|
});
|
|
61
65
|
});
|
|
62
66
|
|
|
67
|
+
describe('#getIdentitiesContractKeys', () => {
|
|
68
|
+
it('should get identities', async () => {
|
|
69
|
+
const result = await platformPromiseClient.getIdentitiesContractKeys(request);
|
|
70
|
+
|
|
71
|
+
expect(result).to.equal(response);
|
|
72
|
+
expect(platformPromiseClient.client.getIdentitiesContractKeys)
|
|
73
|
+
.to.be.calledOnceWith(request);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should throw an error when metadata is not an object', async () => {
|
|
77
|
+
try {
|
|
78
|
+
platformPromiseClient.getIdentitiesContractKeys({}, 'metadata');
|
|
79
|
+
|
|
80
|
+
expect.fail('Error was not thrown');
|
|
81
|
+
} catch (e) {
|
|
82
|
+
expect(e.message).to.equal('metadata must be an object');
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
63
87
|
describe('#getDataContract', () => {
|
|
64
88
|
it('should get data contract', async () => {
|
|
65
89
|
const result = await platformPromiseClient.getDataContract(request);
|
|
@@ -98,7 +122,7 @@ describe('PlatformPromiseClient', () => {
|
|
|
98
122
|
});
|
|
99
123
|
|
|
100
124
|
describe('#getProtocolVersionUpgradeVoteStatus', () => {
|
|
101
|
-
it('should get version upgrade
|
|
125
|
+
it('should get version upgrade votes status', async () => {
|
|
102
126
|
const result = await platformPromiseClient.getProtocolVersionUpgradeVoteStatus(request);
|
|
103
127
|
|
|
104
128
|
expect(result).to.equal(response);
|
|
@@ -116,4 +140,34 @@ describe('PlatformPromiseClient', () => {
|
|
|
116
140
|
.to.be.calledOnceWith(request);
|
|
117
141
|
});
|
|
118
142
|
});
|
|
143
|
+
|
|
144
|
+
describe('#getIdentityContractNonce', () => {
|
|
145
|
+
it('should get identity contract nonce', async () => {
|
|
146
|
+
const result = await platformPromiseClient.getIdentityContractNonce(request);
|
|
147
|
+
|
|
148
|
+
expect(result).to.equal(response);
|
|
149
|
+
expect(platformPromiseClient.client.getIdentityContractNonce)
|
|
150
|
+
.to.be.calledOnceWith(request);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('#getIdentityNonce', () => {
|
|
155
|
+
it('should get identity nonce', async () => {
|
|
156
|
+
const result = await platformPromiseClient.getIdentityNonce(request);
|
|
157
|
+
|
|
158
|
+
expect(result).to.equal(response);
|
|
159
|
+
expect(platformPromiseClient.client.getIdentityNonce)
|
|
160
|
+
.to.be.calledOnceWith(request);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe('#getIdentityKeys', () => {
|
|
165
|
+
it('should get identity keys', async () => {
|
|
166
|
+
const result = await platformPromiseClient.getIdentityKeys(request);
|
|
167
|
+
|
|
168
|
+
expect(result).to.equal(response);
|
|
169
|
+
expect(platformPromiseClient.client.getIdentityKeys)
|
|
170
|
+
.to.be.calledOnceWith(request);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
119
173
|
});
|
|
@@ -14,8 +14,11 @@ describe('getCoreDefinition', () => {
|
|
|
14
14
|
expect(coreDefinition.service).to.have.property('getTransaction');
|
|
15
15
|
expect(coreDefinition.service.getTransaction.path).to.equal('/org.dash.platform.dapi.v0.Core/getTransaction');
|
|
16
16
|
|
|
17
|
-
expect(coreDefinition.service).to.have.property('
|
|
18
|
-
expect(coreDefinition.service.
|
|
17
|
+
expect(coreDefinition.service).to.have.property('getBlockchainStatus');
|
|
18
|
+
expect(coreDefinition.service.getBlockchainStatus.path).to.equal('/org.dash.platform.dapi.v0.Core/getBlockchainStatus');
|
|
19
|
+
|
|
20
|
+
expect(coreDefinition.service).to.have.property('getMasternodeStatus');
|
|
21
|
+
expect(coreDefinition.service.getMasternodeStatus.path).to.equal('/org.dash.platform.dapi.v0.Core/getMasternodeStatus');
|
|
19
22
|
|
|
20
23
|
expect(coreDefinition.service).to.have.property('getBlock');
|
|
21
24
|
expect(coreDefinition.service.getBlock.path).to.equal('/org.dash.platform.dapi.v0.Core/getBlock');
|