Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sdk): add NFT actions in the JS Dash SDK #2444

Open
wants to merge 33 commits into
base: v2.0-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3b511ce
feat(wasm-dpp): add transfer transition to documents batch wip
pshenmic Oct 5, 2024
d3383a1
feat(js-dash-sk): add transfer to document broadcast
pshenmic Oct 5, 2024
fae5915
fix(dpp): add missing import
pshenmic Oct 5, 2024
fd48355
feat(js-dash-sdk): add transfer function wip
pshenmic Oct 5, 2024
e17f1a1
Merge remote-tracking branch 'refs/remotes/origin/v1.7-dev' into feat…
pshenmic Dec 1, 2024
5fd4329
Merge remote-tracking branch 'refs/remotes/origin/v1.7-dev' into feat…
pshenmic Dec 3, 2024
10998f7
Merge remote-tracking branch 'origin/v1.8-dev' into feat/document-tra…
pshenmic Dec 23, 2024
fbe5dbc
feat(js-sdk): implement working document transfers
pshenmic Dec 24, 2024
8f79b69
chore(js-sdk): cleanup
pshenmic Dec 24, 2024
9925a68
chore(js-sdk): cleanup
pshenmic Dec 24, 2024
e8defe8
chore(wasm-dpp): cleanup
pshenmic Dec 24, 2024
1f0f7c6
chore(js-sdk): cleanup
pshenmic Dec 24, 2024
43cc7f1
chore(js-sdk): revert
pshenmic Dec 24, 2024
cf99fe6
chore(js-sdk): cleanup
pshenmic Dec 24, 2024
44df2e6
chore(js-sdk): cleanup
pshenmic Dec 24, 2024
5894a7f
chore(js-sdk): cleanup
pshenmic Dec 24, 2024
d7d5d90
chore(js-sdk): update doc
pshenmic Dec 24, 2024
2131f00
chore(wasm-dpp): cleanup
pshenmic Dec 24, 2024
9bca0cd
feat(wasm-dpp): add nft operations
pshenmic Jan 20, 2025
9dad661
feat(js-sdk): add transfer def in Platform.ts
pshenmic Jan 20, 2025
9c9c913
Merge branch 'refs/heads/feat/document-transfer' into feat/wasm-dpp-nft
pshenmic Jan 26, 2025
cbc86c4
feat(js-dash-sdk): uncomment
pshenmic Jan 26, 2025
7940a09
feat(wasm-dpp): move nft create state transition from extended docume…
pshenmic Jan 30, 2025
dac6932
fix(js-dash-sdk): fix types
pshenmic Jan 30, 2025
b7da382
fix(js-dash-sdk): finalize nft transitions
pshenmic Jan 31, 2025
ccf0921
Merge branch 'v2.0-dev' into feat/wasm-dpp-nft
pshenmic Jan 31, 2025
1a2520e
fix(wasm-dpp): lint fix
pshenmic Jan 31, 2025
dbf1b7c
chore(wasm-dpp): remove unused
pshenmic Jan 31, 2025
1207597
feat(js-dash-sdk): add NFT state transitions docs
pshenmic Jan 31, 2025
3443b3f
chore(wasm-dpp): fix lint
pshenmic Jan 31, 2025
16e2a50
chore(rs-dpp): fix lint
pshenmic Jan 31, 2025
cfe2b60
fix(rs-dpp): fix features
pshenmic Jan 31, 2025
eb4c953
fix(rs-dpp): lint fix
pshenmic Jan 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@
documents: {
create?: ExtendedDocument[],
replace?: ExtendedDocument[],
delete?: ExtendedDocument[]
delete?: ExtendedDocument[],
transfer?: ExtendedDocument[]
},
identity: any,
options: any,
pshenmic marked this conversation as resolved.
Show resolved Hide resolved
): Promise<any> {
console.log(documents)

Check failure on line 27 in packages/js-dash-sdk/src/SDK/Client/Platform/methods/documents/broadcast.ts

View workflow job for this annotation

GitHub Actions / JS packages (dash) / Linting

Missing semicolon
this.logger.debug('[Document#broadcast] Broadcast documents', {
create: documents.create?.length || 0,
replace: documents.replace?.length || 0,
delete: documents.delete?.length || 0,
transfer: documents.transfer?.length || 0,
});
await this.initialize();

Expand All @@ -36,20 +40,25 @@
...(documents.create || []),
...(documents.replace || []),
...(documents.delete || []),
...(documents.transfer || []),
][0]?.getDataContractId();

if (!dataContractId) {
throw new Error('Data contract ID is not found');
}

if (documents.transfer?.length && !options.recipient) {
throw new Error('Receiver identity is not found for transfer transition');
}
pshenmic marked this conversation as resolved.
Show resolved Hide resolved

const identityContractNonce = await this.nonceManager
.bumpIdentityContractNonce(identityId, dataContractId);

const documentsBatchTransition = dpp.document.createStateTransition(documents, {
[identityId.toString()]: {
[dataContractId.toString()]: identityContractNonce,
},
});
}, options.recipient, options.price);

this.logger.silly('[Document#broadcast] Created documents batch transition');

Expand Down Expand Up @@ -79,6 +88,7 @@
create: documents.create?.length || 0,
replace: documents.replace?.length || 0,
delete: documents.delete?.length || 0,
transfer: documents.transfer?.length || 0,
});

return documentsBatchTransition;
Expand Down
5 changes: 4 additions & 1 deletion packages/rs-dpp/src/document/document_factory/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::state_transition::documents_batch_transition::{
};
use crate::util::entropy_generator::EntropyGenerator;
pub use v0::DocumentFactoryV0;
use crate::fee::Credits;

/// # Document Factory
///
Expand Down Expand Up @@ -120,9 +121,11 @@ impl DocumentFactory {
),
>,
nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce
recipient: Option<Identifier>,
price: Option<Credits>,
) -> Result<DocumentsBatchTransition, ProtocolError> {
match self {
DocumentFactory::V0(v0) => v0.create_state_transition(documents_iter, nonce_counter),
DocumentFactory::V0(v0) => v0.create_state_transition(documents_iter, nonce_counter, recipient, price),
}
}

Expand Down
150 changes: 149 additions & 1 deletion packages/rs-dpp/src/document/document_factory/v0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ use crate::state_transition::documents_batch_transition::{
DocumentsBatchTransition, DocumentsBatchTransitionV0,
};
use itertools::Itertools;
use crate::fee::Credits;
use crate::state_transition::documents_batch_transition::document_transition::{DocumentPurchaseTransition, DocumentTransferTransition, DocumentUpdatePriceTransition};

const PROPERTY_FEATURE_VERSION: &str = "$version";
const PROPERTY_ENTROPY: &str = "$entropy";
Expand Down Expand Up @@ -209,7 +211,9 @@ impl DocumentFactoryV0 {
Vec<(Document, DocumentTypeRef<'a>, Bytes32)>,
),
>,
nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce
nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce,
recipient: Option<Identifier>,
price: Option<Credits>
) -> Result<DocumentsBatchTransition, ProtocolError> {
let platform_version = PlatformVersion::get(self.protocol_version)?;
let documents: Vec<(
Expand Down Expand Up @@ -262,6 +266,33 @@ impl DocumentFactoryV0 {
nonce_counter,
platform_version,
),
DocumentTransitionActionType::Transfer => Self::document_transfer_transitions(
documents
.into_iter()
.map(|(document, document_type, _)| (document, document_type))
.collect(),
nonce_counter,
platform_version,
recipient.unwrap()
),
pshenmic marked this conversation as resolved.
Show resolved Hide resolved
DocumentTransitionActionType::UpdatePrice => Self::document_update_price_transitions(
documents
.into_iter()
.map(|(document, document_type, _)| (document, document_type))
.collect(),
nonce_counter,
platform_version,
price.unwrap()
),
pshenmic marked this conversation as resolved.
Show resolved Hide resolved
DocumentTransitionActionType::Purchase => Self::document_purchase_transitions(
documents
.into_iter()
.map(|(document, document_type, _)| (document, document_type))
.collect(),
nonce_counter,
platform_version,
price.unwrap()
),
pshenmic marked this conversation as resolved.
Show resolved Hide resolved
_ => Err(ProtocolError::InvalidStateTransitionType(
"action type not accounted for".to_string(),
)),
Expand Down Expand Up @@ -548,6 +579,123 @@ impl DocumentFactoryV0 {
.collect()
}

#[cfg(feature = "state-transitions")]
fn document_transfer_transitions(
documents: Vec<(Document, DocumentTypeRef)>,
nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce
platform_version: &PlatformVersion,
recipient_owner_id: Identifier
) -> Result<Vec<DocumentTransition>, ProtocolError> {
documents
.into_iter()
.map(|(document, document_type)| {
if !document_type.documents_transferable().is_transferable() {
return Err(DocumentError::TryingToTransferNonTransferableDocument {
document: Box::new(document),
}
.into());
}
let Some(_document_revision) = document.revision() else {
return Err(DocumentError::RevisionAbsentError {
document: Box::new(document),
}
.into());
};

let nonce = nonce_counter
.entry((document.owner_id(), document_type.data_contract_id()))
.or_default();
let transition = DocumentTransferTransition::from_document(
document,
document_type,
*nonce,
recipient_owner_id,
platform_version,
None,
None,
)?;

*nonce += 1;

Ok(transition.into())
})
.collect()
}

#[cfg(feature = "state-transitions")]
fn document_update_price_transitions(
documents: Vec<(Document, DocumentTypeRef)>,
nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce
platform_version: &PlatformVersion,
price: Credits
) -> Result<Vec<DocumentTransition>, ProtocolError> {
documents
.into_iter()
.map(|(document, document_type)| {
let Some(_document_revision) = document.revision() else {
return Err(DocumentError::RevisionAbsentError {
document: Box::new(document),
}
.into());
};

let nonce = nonce_counter
.entry((document.owner_id(), document_type.data_contract_id()))
.or_default();
let transition = DocumentUpdatePriceTransition::from_document(
document,
document_type,
price,
*nonce,
platform_version,
None,
None,
)?;

*nonce += 1;

Ok(transition.into())
})
.collect()
}

#[cfg(feature = "state-transitions")]
fn document_purchase_transitions(
documents: Vec<(Document, DocumentTypeRef)>,
nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce
platform_version: &PlatformVersion,
price: Credits
) -> Result<Vec<DocumentTransition>, ProtocolError> {
documents
.into_iter()
.map(|(document, document_type)| {
let Some(_document_revision) = document.revision() else {
return Err(DocumentError::RevisionAbsentError {
document: Box::new(document),
}
.into());
};

let nonce = nonce_counter
.entry((document.owner_id(), document_type.data_contract_id()))
.or_default();
let transition = DocumentPurchaseTransition::from_document(
document,
document_type,
price,
*nonce,
platform_version,
None,
None,
)?;

*nonce += 1;

Ok(transition.into())
})
.collect()
}

fn is_ownership_the_same<'a>(ids: impl IntoIterator<Item = &'a Identifier>) -> bool {
ids.into_iter().all_equal()
}
Expand Down
3 changes: 3 additions & 0 deletions packages/rs-dpp/src/document/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ pub enum DocumentError {
#[error("Trying to delete indelible document")]
TryingToDeleteIndelibleDocument { document: Box<Document> },

#[error("Trying to transfer non-transferable document")]
TryingToTransferNonTransferableDocument { document: Box<Document> },

#[error("Documents have mixed owner ids")]
MismatchOwnerIdsError { documents: Vec<Document> },

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ impl DocumentsBatchTransitionInternalTransformerV0 for DocumentsBatchTransition
StateError::InvalidDocumentRevisionError(InvalidDocumentRevisionError::new(
document_id,
Some(previous_revision),
transition_revision,
expected_revision,
)),
))
}
Expand Down
10 changes: 7 additions & 3 deletions packages/wasm-dpp/src/document/document_facade.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use std::rc::Rc;
use wasm_bindgen::{prelude::*, JsValue};

use dpp::fee::Credits;
use dpp::identifier::Identifier;

Check warning on line 4 in packages/wasm-dpp/src/document/document_facade.rs

View workflow job for this annotation

GitHub Actions / Rust packages (wasm-dpp) / Linting

unused import: `dpp::identifier::Identifier`

warning: unused import: `dpp::identifier::Identifier` --> packages/wasm-dpp/src/document/document_facade.rs:4:5 | 4 | use dpp::identifier::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default
use crate::document::factory::DocumentFactoryWASM;
use crate::{DataContractWasm, ExtendedDocumentWasm};

use crate::document::state_transition::document_batch_transition::DocumentsBatchTransitionWasm;
use crate::identifier::IdentifierWrapper;

#[derive(Clone)]
#[wasm_bindgen(js_name=DocumentFacade)]
Expand Down Expand Up @@ -95,10 +97,12 @@
pub fn create_state_transition(
&self,
documents: &JsValue,
nonce_counter_value: &js_sys::Object, //IdentityID/ContractID -> nonce
nonce_counter_value: &js_sys::Object, //IdentityID/ContractID -> nonce,
recipient: Option<IdentifierWrapper>,
price: Option<Credits>
) -> Result<DocumentsBatchTransitionWasm, JsValue> {
self.factory
.create_state_transition(documents, nonce_counter_value)
.create_state_transition(documents, nonce_counter_value, recipient, price)
}

// /// Creates Documents State Transition
Expand Down
5 changes: 5 additions & 0 deletions packages/wasm-dpp/src/document/errors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::document::errors::invalid_action_error::InvalidActionError;
use crate::document::errors::revision_absent_error::RevisionAbsentError;
use crate::document::errors::trying_to_delete_immutable_document_error::TryingToDeleteImmutableDocumentError;
use crate::document::errors::trying_to_replace_immutable_document_error::TryingToReplaceImmutableDocumentError;
use crate::document::errors::trying_to_transfer_nontransferable_document_error::TryingToTransferNonTransferableDocumentError;
pub use document_already_exists_error::*;
pub use document_not_provided_error::*;
use dpp::document::errors::DocumentError;
Expand All @@ -32,6 +33,7 @@ mod no_documents_supplied_error;
mod revision_absent_error;
mod trying_to_delete_immutable_document_error;
mod trying_to_replace_immutable_document_error;
mod trying_to_transfer_nontransferable_document_error;

pub fn from_document_to_js_error(e: DocumentError) -> JsValue {
match e {
Expand Down Expand Up @@ -77,6 +79,9 @@ pub fn from_document_to_js_error(e: DocumentError) -> JsValue {
DocumentError::InvalidActionError(action) => InvalidActionError::new(action.into()).into(),
DocumentError::TryingToDeleteIndelibleDocument { document } => {
TryingToDeleteImmutableDocumentError::new((*document).into()).into()
},
DocumentError::TryingToTransferNonTransferableDocument { document } => {
TryingToTransferNonTransferableDocumentError::new((*document).into()).into()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use crate::document::DocumentWasm;
use thiserror::Error;

use super::*;

#[wasm_bindgen]
#[derive(Error, Debug)]
#[error("Trying to transfer an non transferable document")]
pub struct TryingToTransferNonTransferableDocumentError {
document: DocumentWasm,
}

#[wasm_bindgen]
impl TryingToTransferNonTransferableDocumentError {
#[wasm_bindgen(constructor)]
pub fn new(document: DocumentWasm) -> Self {
TryingToTransferNonTransferableDocumentError { document }
}
}
5 changes: 2 additions & 3 deletions packages/wasm-dpp/src/document/extended_document.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use dpp::document::{
DocumentV0Getters, DocumentV0Setters, ExtendedDocument, EXTENDED_DOCUMENT_IDENTIFIER_FIELDS,
};
use dpp::document::{DocumentV0Getters, DocumentV0Setters, ExtendedDocument, EXTENDED_DOCUMENT_IDENTIFIER_FIELDS};
use serde_json::Value as JsonValue;

use dpp::platform_value::{Bytes32, Value};
Expand All @@ -22,6 +20,7 @@
#[allow(deprecated)] // BinaryType is unsed in unused code below
use crate::document::BinaryType;
use crate::document::{ConversionOptions, DocumentWasm};
use crate::document_batch_transition::DocumentsBatchTransitionWasm;

Check warning on line 23 in packages/wasm-dpp/src/document/extended_document.rs

View workflow job for this annotation

GitHub Actions / Rust packages (wasm-dpp) / Linting

unused import: `crate::document_batch_transition::DocumentsBatchTransitionWasm`

warning: unused import: `crate::document_batch_transition::DocumentsBatchTransitionWasm` --> packages/wasm-dpp/src/document/extended_document.rs:23:5 | 23 | use crate::document_batch_transition::DocumentsBatchTransitionWasm; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
use crate::errors::RustConversionError;
use crate::identifier::{identifier_from_js_value, IdentifierWrapper};
use crate::lodash::lodash_set;
Expand Down
Loading
Loading