Skip to content

Commit e735313

Browse files
authored
feat: add token transitions to SDK and DAPI (#2434)
1 parent f609bcf commit e735313

File tree

35 files changed

+2001
-185
lines changed

35 files changed

+2001
-185
lines changed

packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js

Lines changed: 158 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,21 @@ const {
33
GetProofsRequest,
44
},
55
} = require('@dashevo/dapi-grpc');
6-
const { StateTransitionTypes } = require('@dashevo/wasm-dpp');
6+
7+
const {
8+
StateTransitionTypes,
9+
TokenTransition,
10+
DocumentTransition,
11+
TokenTransitionType,
12+
} = require('@dashevo/wasm-dpp');
13+
const { GetDataContractRequest } = require('@dashevo/dapi-grpc/clients/platform/v0/web/platform_pb');
714

815
/**
916
* @param {PlatformPromiseClient} driveClient
17+
* @param {DashPlatformProtocol} dpp
1018
* @return {fetchProofForStateTransition}
1119
*/
12-
function fetchProofForStateTransitionFactory(driveClient) {
20+
function fetchProofForStateTransitionFactory(driveClient, dpp) {
1321
/**
1422
* @typedef {fetchProofForStateTransition}
1523
* @param {AbstractStateTransition} stateTransition
@@ -22,25 +30,160 @@ function fetchProofForStateTransitionFactory(driveClient) {
2230

2331
const requestV0 = new GetProofsRequestV0();
2432

33+
let dataContractsCache = {};
34+
2535
if (stateTransition.isDocumentStateTransition()) {
26-
const { DocumentRequest } = GetProofsRequestV0;
36+
const {
37+
DocumentRequest,
38+
IdentityTokenBalanceRequest,
39+
IdentityTokenInfoRequest,
40+
TokenStatusRequest,
41+
} = GetProofsRequestV0;
2742

28-
const documentsList = stateTransition.getTransitions().map((documentTransition) => {
29-
const documentRequest = new DocumentRequest();
30-
documentRequest.setContractId(documentTransition.getDataContractId().toBuffer());
31-
documentRequest.setDocumentType(documentTransition.getType());
32-
documentRequest.setDocumentId(documentTransition.getId().toBuffer());
43+
const documentsList = [];
44+
const identityTokenBalancesList = [];
45+
const identityTokenInfosList = [];
46+
const tokenStatusesList = [];
3347

34-
const status = documentTransition.hasPrefundedBalance()
35-
? DocumentRequest.DocumentContestedStatus.CONTESTED
36-
: DocumentRequest.DocumentContestedStatus.NOT_CONTESTED;
48+
for (const batchedTransition of stateTransition.getTransitions()) {
49+
if (batchedTransition instanceof TokenTransition) {
50+
switch (batchedTransition.getTransitionType()) {
51+
case TokenTransitionType.Burn: {
52+
const request = new IdentityTokenBalanceRequest({
53+
tokenId: batchedTransition.getTokenId()
54+
.toBuffer(),
55+
identityId: stateTransition.getOwnerId()
56+
.toBuffer(),
57+
});
3758

38-
documentRequest.setDocumentContestedStatus(status);
59+
identityTokenBalancesList.push(request);
60+
break;
61+
}
62+
case TokenTransitionType.Mint: {
63+
// Fetch data contract to determine correct recipient identity
64+
const dataContractId = batchedTransition.getDataContractId();
65+
const dataContractIdString = dataContractId.toString();
3966

40-
return documentRequest;
41-
});
67+
if (!dataContractsCache[dataContractIdString]) {
68+
const dataContractRequestV0 = new GetDataContractRequest.GetDataContractRequestV0({
69+
id: dataContractId.toBuffer(),
70+
});
71+
72+
const dataContractRequest = new GetDataContractRequest();
73+
dataContractRequest.setV0(dataContractRequestV0);
74+
75+
const dataContractResponse = await driveClient.getDataContract(dataContractRequest);
76+
77+
const dataContractBuffer = Buffer.from(
78+
dataContractResponse.getV0().getDataContract_asU8(),
79+
);
80+
81+
dataContractsCache[dataContractIdString] = await dpp.dataContract
82+
.createFromBuffer(dataContractBuffer);
83+
}
84+
85+
const dataContract = dataContractsCache[dataContractIdString];
86+
87+
const tokenConfiguration = dataContract.getTokenConfiguration(
88+
batchedTransition.getTokenContractPosition(),
89+
);
90+
91+
const request = new IdentityTokenBalanceRequest({
92+
tokenId: batchedTransition.getTokenId()
93+
.toBuffer(),
94+
identityId: batchedTransition.toTransition().getRecipientId(tokenConfiguration)
95+
.toBuffer(),
96+
});
97+
98+
identityTokenBalancesList.push(request);
99+
break;
100+
}
101+
case TokenTransitionType.Transfer: {
102+
const requestSender = new IdentityTokenBalanceRequest({
103+
tokenId: batchedTransition.getTokenId()
104+
.toBuffer(),
105+
identityId: stateTransition.getOwnerId().toBuffer(),
106+
});
107+
108+
const requestRecipient = new IdentityTokenBalanceRequest({
109+
tokenId: batchedTransition.getTokenId()
110+
.toBuffer(),
111+
identityId: batchedTransition.toTransition().getRecipientId()
112+
.toBuffer(),
113+
});
114+
115+
identityTokenBalancesList.push(requestSender, requestRecipient);
116+
break;
117+
}
118+
case TokenTransitionType.DestroyFrozenFunds: {
119+
const request = new IdentityTokenBalanceRequest({
120+
tokenId: batchedTransition.getTokenId()
121+
.toBuffer(),
122+
identityId: batchedTransition.toTransition().getFrozenIdentityId()
123+
.toBuffer(),
124+
});
125+
126+
identityTokenBalancesList.push(request);
127+
break;
128+
}
129+
case TokenTransitionType.EmergencyAction:
130+
{
131+
const request = new TokenStatusRequest({
132+
tokenId: batchedTransition.getTokenId()
133+
.toBuffer(),
134+
});
42135

43-
requestV0.setDocumentsList(documentsList);
136+
tokenStatusesList.push(request);
137+
break;
138+
}
139+
case TokenTransitionType.Freeze:
140+
case TokenTransitionType.Unfreeze: {
141+
const request = new IdentityTokenInfoRequest({
142+
tokenId: batchedTransition.getTokenId()
143+
.toBuffer(),
144+
identityId: batchedTransition.toTransition().getFrozenIdentityId()
145+
.toBuffer(),
146+
});
147+
148+
identityTokenInfosList.push(request);
149+
break;
150+
}
151+
default:
152+
throw new Error(`Unsupported token transition type ${batchedTransition.getTransitionType()}`);
153+
}
154+
} else if (batchedTransition instanceof DocumentTransition) {
155+
const documentRequest = new DocumentRequest();
156+
documentRequest.setContractId(batchedTransition.getDataContractId().toBuffer());
157+
documentRequest.setDocumentType(batchedTransition.getType());
158+
documentRequest.setDocumentId(batchedTransition.getId().toBuffer());
159+
160+
const status = batchedTransition.hasPrefundedBalance()
161+
? DocumentRequest.DocumentContestedStatus.CONTESTED
162+
: DocumentRequest.DocumentContestedStatus.NOT_CONTESTED;
163+
164+
documentRequest.setDocumentContestedStatus(status);
165+
166+
documentsList.push(documentRequest);
167+
} else {
168+
throw new Error(`Unsupported batched transition type ${batchedTransition.constructor.name}`);
169+
}
170+
}
171+
172+
if (documentsList.length > 0) {
173+
requestV0.setDocumentsList(documentsList);
174+
}
175+
176+
if (identityTokenBalancesList.length > 0) {
177+
requestV0.setIdentityTokenBalancesList(identityTokenBalancesList);
178+
}
179+
180+
if (identityTokenInfosList.length > 0) {
181+
requestV0.setIdentityTokenInfosList(identityTokenInfosList);
182+
}
183+
184+
if (tokenStatusesList.length > 0) {
185+
requestV0.setTokenStatusesList(tokenStatusesList);
186+
}
44187
} if (stateTransition.isIdentityStateTransition()) {
45188
const { IdentityRequest } = GetProofsRequestV0;
46189

packages/rs-dpp/src/data_contract/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::version::{FeatureVersion, PlatformVersion};
5050
use crate::ProtocolError;
5151
use crate::ProtocolError::{PlatformDeserializationError, PlatformSerializationError};
5252

53-
use crate::data_contract::associated_token::token_configuration::TokenConfiguration;
53+
pub use crate::data_contract::associated_token::token_configuration::TokenConfiguration;
5454
use crate::data_contract::group::Group;
5555
use crate::data_contract::v0::DataContractV0;
5656
use crate::data_contract::v1::DataContractV1;

packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/mod.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ use platform_value::Identifier;
1212
#[cfg(feature = "state-transition-serde-conversion")]
1313
use serde::{Deserialize, Serialize};
1414

15+
pub type SharedEncryptedNote = (SenderKeyIndex, RecipientKeyIndex, Vec<u8>);
16+
pub type PrivateEncryptedNote = (
17+
RootEncryptionKeyIndex,
18+
DerivationEncryptionKeyIndex,
19+
Vec<u8>,
20+
);
21+
1522
mod property_names {
1623
pub const AMOUNT: &str = "$amount";
1724
pub const RECIPIENT_OWNER_ID: &str = "recipientOwnerId";
@@ -53,15 +60,11 @@ pub struct TokenTransferTransitionV0 {
5360
feature = "state-transition-serde-conversion",
5461
serde(rename = "sharedEncryptedNote")
5562
)]
56-
pub shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec<u8>)>,
63+
pub shared_encrypted_note: Option<SharedEncryptedNote>,
5764
/// An optional private encrypted note
5865
#[cfg_attr(
5966
feature = "state-transition-serde-conversion",
6067
serde(rename = "privateEncryptedNote")
6168
)]
62-
pub private_encrypted_note: Option<(
63-
RootEncryptionKeyIndex,
64-
DerivationEncryptionKeyIndex,
65-
Vec<u8>,
66-
)>,
69+
pub private_encrypted_note: Option<PrivateEncryptedNote>,
6770
}

packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/v0_methods.rs

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::prelude::{DerivationEncryptionKeyIndex, RecipientKeyIndex, RootEncryp
33
use crate::state_transition::batch_transition::batched_transition::token_transfer_transition::TokenTransferTransitionV0;
44
use crate::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors;
55
use crate::state_transition::batch_transition::token_base_transition::TokenBaseTransition;
6+
use crate::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote};
67

78
impl TokenBaseTransitionAccessors for TokenTransferTransitionV0 {
89
fn base(&self) -> &TokenBaseTransition {
@@ -44,16 +45,13 @@ pub trait TokenTransferTransitionV0Methods: TokenBaseTransitionAccessors {
4445
fn set_public_note(&mut self, public_note: Option<String>);
4546

4647
/// Returns the `shared_encrypted_note` field of the `TokenTransferTransitionV0`.
47-
fn shared_encrypted_note(&self) -> Option<&(SenderKeyIndex, RecipientKeyIndex, Vec<u8>)>;
48+
fn shared_encrypted_note(&self) -> Option<&SharedEncryptedNote>;
4849

4950
/// Returns the owned `shared_encrypted_note` field of the `TokenTransferTransitionV0`.
50-
fn shared_encrypted_note_owned(self) -> Option<(SenderKeyIndex, RecipientKeyIndex, Vec<u8>)>;
51+
fn shared_encrypted_note_owned(self) -> Option<SharedEncryptedNote>;
5152

5253
/// Sets the value of the `shared_encrypted_note` field in the `TokenTransferTransitionV0`.
53-
fn set_shared_encrypted_note(
54-
&mut self,
55-
shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec<u8>)>,
56-
);
54+
fn set_shared_encrypted_note(&mut self, shared_encrypted_note: Option<SharedEncryptedNote>);
5755

5856
/// Returns the `private_encrypted_note` field of the `TokenTransferTransitionV0`.
5957
fn private_encrypted_note(
@@ -74,26 +72,15 @@ pub trait TokenTransferTransitionV0Methods: TokenBaseTransitionAccessors {
7472
)>;
7573

7674
/// Sets the value of the `private_encrypted_note` field in the `TokenTransferTransitionV0`.
77-
fn set_private_encrypted_note(
78-
&mut self,
79-
private_encrypted_note: Option<(
80-
RootEncryptionKeyIndex,
81-
DerivationEncryptionKeyIndex,
82-
Vec<u8>,
83-
)>,
84-
);
75+
fn set_private_encrypted_note(&mut self, private_encrypted_note: Option<PrivateEncryptedNote>);
8576

8677
/// Returns all notes (public, shared, and private) as owned values in a tuple.
8778
fn notes_owned(
8879
self,
8980
) -> (
9081
Option<String>,
91-
Option<(SenderKeyIndex, RecipientKeyIndex, Vec<u8>)>,
92-
Option<(
93-
RootEncryptionKeyIndex,
94-
DerivationEncryptionKeyIndex,
95-
Vec<u8>,
96-
)>,
82+
Option<SharedEncryptedNote>,
83+
Option<PrivateEncryptedNote>,
9784
);
9885

9986
/// Returns all notes (public, shared, and private) as cloned values in a tuple.
@@ -142,18 +129,15 @@ impl TokenTransferTransitionV0Methods for TokenTransferTransitionV0 {
142129
self.public_note = public_note;
143130
}
144131

145-
fn shared_encrypted_note(&self) -> Option<&(SenderKeyIndex, RecipientKeyIndex, Vec<u8>)> {
132+
fn shared_encrypted_note(&self) -> Option<&SharedEncryptedNote> {
146133
self.shared_encrypted_note.as_ref()
147134
}
148135

149-
fn shared_encrypted_note_owned(self) -> Option<(SenderKeyIndex, RecipientKeyIndex, Vec<u8>)> {
136+
fn shared_encrypted_note_owned(self) -> Option<SharedEncryptedNote> {
150137
self.shared_encrypted_note
151138
}
152139

153-
fn set_shared_encrypted_note(
154-
&mut self,
155-
shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec<u8>)>,
156-
) {
140+
fn set_shared_encrypted_note(&mut self, shared_encrypted_note: Option<SharedEncryptedNote>) {
157141
self.shared_encrypted_note = shared_encrypted_note;
158142
}
159143

@@ -177,27 +161,16 @@ impl TokenTransferTransitionV0Methods for TokenTransferTransitionV0 {
177161
self.private_encrypted_note
178162
}
179163

180-
fn set_private_encrypted_note(
181-
&mut self,
182-
private_encrypted_note: Option<(
183-
RootEncryptionKeyIndex,
184-
DerivationEncryptionKeyIndex,
185-
Vec<u8>,
186-
)>,
187-
) {
164+
fn set_private_encrypted_note(&mut self, private_encrypted_note: Option<PrivateEncryptedNote>) {
188165
self.private_encrypted_note = private_encrypted_note;
189166
}
190167

191168
fn notes_owned(
192169
self,
193170
) -> (
194171
Option<String>,
195-
Option<(SenderKeyIndex, RecipientKeyIndex, Vec<u8>)>,
196-
Option<(
197-
RootEncryptionKeyIndex,
198-
DerivationEncryptionKeyIndex,
199-
Vec<u8>,
200-
)>,
172+
Option<SharedEncryptedNote>,
173+
Option<PrivateEncryptedNote>,
201174
) {
202175
(
203176
self.public_note,

0 commit comments

Comments
 (0)