Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
7698392
feat: add wasm-dpp2
shumkov Oct 4, 2025
e99494f
refactor: remove WASM postfix from JS names
shumkov Oct 4, 2025
ee56d78
refactor: rename WASM postfix to Wasm
shumkov Oct 4, 2025
2814fe1
ci: add to CI
shumkov Oct 4, 2025
24711ff
chore: switch to local dpp
shumkov Oct 4, 2025
bc476ce
feat: integrate wasm-dpp2 entities
shumkov Oct 6, 2025
84a4ce9
refactor: rename `hex` to `toHex`
shumkov Oct 6, 2025
aa70d63
refactor: rename `bytes` to `toBytes`
shumkov Oct 6, 2025
44fd7d9
refactor: rename `toJson` to `toJSON`
shumkov Oct 6, 2025
bd0c39a
refactor: return error instead of jsvalue
shumkov Oct 6, 2025
9d4796b
refactor: replace jsvalue to error
shumkov Oct 7, 2025
06c576f
refactor: accomplish error refactoring
shumkov Oct 7, 2025
ee6ecc2
refactor: structure modules
shumkov Oct 7, 2025
3adc61d
refactor: downgrade to file modules
shumkov Oct 7, 2025
f1d296d
refactor: move code from mod.rs
shumkov Oct 7, 2025
77e95ae
refactor: use entities for data contract and documents
shumkov Oct 8, 2025
6796ba3
feat: epoch entities
shumkov Oct 8, 2025
8717ec2
feat: groups
shumkov Oct 9, 2025
b62ce96
refactor: group responses
shumkov Oct 9, 2025
9703af9
refactor: identity and group
shumkov Oct 9, 2025
cb0ad52
refactor: protocol
shumkov Oct 9, 2025
d09e11f
refactor: system
shumkov Oct 9, 2025
03abb96
refactor: add tokens
shumkov Oct 10, 2025
e9f6f2e
refactor: add typing to vote queries
shumkov Oct 15, 2025
2a2142b
Merge branch 'v2.1-dev' into feat/sdk/entities
QuantumExplorer Oct 24, 2025
7717fed
refactor: plain object query params
shumkov Oct 28, 2025
252e4e6
refactor: cleanup voting interface
shumkov Oct 28, 2025
7af57a7
chore: update SDK interfaces
shumkov Oct 29, 2025
267ae9c
Merge branch 'v2.2-dev' into feat/sdk/entities
shumkov Oct 29, 2025
fc83930
build: fix docker image
shumkov Oct 30, 2025
3dbeddc
build: do not build wasm-dpp2 by default
shumkov Oct 30, 2025
c24080d
build: build wasm-dpp2 by default but not for docker image
shumkov Oct 30, 2025
fadde6d
chore: remove unused deps
shumkov Oct 30, 2025
7572cff
chore: remove web-sys deps
shumkov Oct 30, 2025
6b636a1
refactor: fix clippy warnings
shumkov Oct 30, 2025
e9f77e2
test: fix contracts test
shumkov Oct 30, 2025
c1559b6
style: formatting
shumkov Oct 30, 2025
de92ae7
chore: remove commented code
shumkov Oct 30, 2025
e346dfa
fix: invalid contested resource value
shumkov Oct 30, 2025
4168580
fix: missing version 10
shumkov Oct 31, 2025
236a680
Update packages/wasm-dpp2/tests/unit/DataContractUpdateStateTransitio…
shumkov Oct 31, 2025
dc34f75
fix: typo
shumkov Oct 31, 2025
175cc08
Update packages/wasm-dpp2/src/state_transitions/batch/token_transitio…
shumkov Oct 31, 2025
136e253
Merge remote-tracking branch 'origin/feat/sdk/entities' into feat/sdk…
shumkov Oct 31, 2025
5f9bed7
Merge branch 'v2.2-dev' into feat/sdk/entities
shumkov Oct 31, 2025
2afb5f3
chore: update lock file
shumkov Oct 31, 2025
b100690
refactor: fix clippy warnings
shumkov Nov 1, 2025
5e0f1b4
Merge remote-tracking branch 'origin/feat/sdk/entities' into feat/sdk…
shumkov Nov 1, 2025
39deaba
feat(sdk): typed identifier
shumkov Nov 1, 2025
85ab1d5
fix: missing import
shumkov Nov 1, 2025
71b73c2
refactor: identifier params
shumkov Nov 1, 2025
3561301
refactor: rename fromValue to fromJSON
shumkov Nov 1, 2025
fcd291a
Merge branch 'feat/sdk/entities' into methods
shumkov Nov 2, 2025
de398f9
refactor(sdk): toObject/toJSON
shumkov Nov 3, 2025
16d7b23
Merge branch 'v2.2-dev' into methods
shumkov Nov 3, 2025
29dd696
fix: broken Cargo.toml
shumkov Nov 3, 2025
4c77e8b
refactor: fix clippy warnings
shumkov Nov 3, 2025
aa0d6e4
style: fix formatting
shumkov Nov 3, 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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/wasm-dpp2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wasm-dpp2"
version = "1.0.5"
version = { workspace = true }
edition = "2024"

[lib]
Expand All @@ -16,6 +16,7 @@ dpp = { path = "../rs-dpp", default-features = false, features = [
"document-json-conversion",
"identity-serialization",
"identity-value-conversion",
"identity-json-conversion",
"data-contract-json-conversion",
"document-value-conversion",
"bls-signatures",
Expand Down
2 changes: 1 addition & 1 deletion packages/wasm-dpp2/src/asset_lock_proof/outpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ impl OutPointWasm {
encode(slice.as_slice(), Hex)
}

#[wasm_bindgen(js_name = "base64")]
#[wasm_bindgen(js_name = "toBase64")]
pub fn to_base64(&self) -> String {
let slice: [u8; 36] = self.0.into();

Expand Down
18 changes: 18 additions & 0 deletions packages/wasm-dpp2/src/asset_lock_proof/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ use crate::enums::lock_types::AssetLockProofTypeWasm;
use crate::error::{WasmDppError, WasmDppResult};
use crate::identifier::IdentifierWasm;
use crate::utils::{IntoWasm, get_class_type};
use dpp::platform_value::Value;
use dpp::prelude::AssetLockProof;
use serde::Serialize;
use serde_json::Value as JsonValue;
use serde_wasm_bindgen::from_value;
use std::convert::TryFrom;
use wasm_bindgen::JsValue;
use wasm_bindgen::prelude::wasm_bindgen;

Expand Down Expand Up @@ -148,6 +152,20 @@ impl AssetLockProofWasm {
.map_err(|e| WasmDppError::serialization(e.to_string()))
}

#[wasm_bindgen(js_name = "fromObject")]
pub fn from_object(js_value: JsValue) -> WasmDppResult<AssetLockProofWasm> {
let json_value: JsonValue =
from_value(js_value).map_err(|err| WasmDppError::serialization(err.to_string()))?;
let value = Value::from(json_value);
let proof = AssetLockProof::try_from(value).map_err(WasmDppError::from)?;
Ok(AssetLockProofWasm(proof))
}

#[wasm_bindgen(js_name = "fromJSON")]
pub fn from_json(js_value: JsValue) -> WasmDppResult<AssetLockProofWasm> {
AssetLockProofWasm::from_object(js_value)
}

#[wasm_bindgen(js_name = "toHex")]
pub fn to_string(&self) -> WasmDppResult<String> {
let json = serde_json::to_string(&self.0)
Expand Down
31 changes: 17 additions & 14 deletions packages/wasm-dpp2/src/core_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,39 +42,42 @@ impl CoreScriptWasm {
}

#[wasm_bindgen(js_name = "newP2PKH")]
pub fn new_p2pkh(js_key_hash: Vec<u8>) -> Self {
let mut key_hash = [0u8; 20];
let bytes = js_key_hash.as_slice();
pub fn new_p2pkh(key_hash: Vec<u8>) -> Self {
let mut key_hash_bytes = [0u8; 20];
let bytes = key_hash.as_slice();
let len = bytes.len().min(32);
key_hash[..len].copy_from_slice(&bytes[..len]);
key_hash_bytes[..len].copy_from_slice(&bytes[..len]);

CoreScriptWasm(CoreScript::new_p2pkh(key_hash))
CoreScriptWasm(CoreScript::new_p2pkh(key_hash_bytes))
}
Comment on lines +45 to 52
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix array bounds issue to prevent panic.

The code uses .min(32) but key_hash_bytes is only a 20-byte array. If the input key_hash has a length between 21-32 bytes, len will exceed 20, causing key_hash_bytes[..len] to panic at runtime.

Apply this diff to fix the bounds check:

     pub fn new_p2pkh(key_hash: Vec<u8>) -> Self {
         let mut key_hash_bytes = [0u8; 20];
         let bytes = key_hash.as_slice();
-        let len = bytes.len().min(32);
+        let len = bytes.len().min(20);
         key_hash_bytes[..len].copy_from_slice(&bytes[..len]);
 
         CoreScriptWasm(CoreScript::new_p2pkh(key_hash_bytes))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn new_p2pkh(key_hash: Vec<u8>) -> Self {
let mut key_hash_bytes = [0u8; 20];
let bytes = key_hash.as_slice();
let len = bytes.len().min(32);
key_hash[..len].copy_from_slice(&bytes[..len]);
key_hash_bytes[..len].copy_from_slice(&bytes[..len]);
CoreScriptWasm(CoreScript::new_p2pkh(key_hash))
CoreScriptWasm(CoreScript::new_p2pkh(key_hash_bytes))
}
pub fn new_p2pkh(key_hash: Vec<u8>) -> Self {
let mut key_hash_bytes = [0u8; 20];
let bytes = key_hash.as_slice();
let len = bytes.len().min(20);
key_hash_bytes[..len].copy_from_slice(&bytes[..len]);
CoreScriptWasm(CoreScript::new_p2pkh(key_hash_bytes))
}
🤖 Prompt for AI Agents
In packages/wasm-dpp2/src/core_script.rs around lines 45 to 52, the code
computes len with .min(32) but copies into a 20-byte array which can panic for
input lengths 21–32; change the bounds calculation to use the destination length
(e.g., bytes.len().min(key_hash_bytes.len()) or .min(20)) so you only copy at
most 20 bytes, then copy that many bytes and construct CoreScriptWasm with the
fixed key_hash_bytes.


#[wasm_bindgen(js_name = "newP2SH")]
pub fn new_p2sh(js_script_hash: Vec<u8>) -> Self {
let mut script_hash = [0u8; 20];
let bytes = js_script_hash.as_slice();
pub fn new_p2sh(script_hash: Vec<u8>) -> Self {
let mut script_hash_bytes = [0u8; 20];
let bytes = script_hash.as_slice();
let len = bytes.len().min(32);
script_hash[..len].copy_from_slice(&bytes[..len]);
script_hash_bytes[..len].copy_from_slice(&bytes[..len]);

let mut bytes = vec![
opcodes::all::OP_HASH160.to_u8(),
opcodes::all::OP_PUSHBYTES_20.to_u8(),
];
bytes.extend_from_slice(&script_hash);
bytes.extend_from_slice(&script_hash_bytes);
bytes.push(opcodes::all::OP_EQUAL.to_u8());
Self::from_bytes(bytes)
}
Comment on lines +55 to 68
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix array bounds issue to prevent panic.

Same issue as new_p2pkh: the code uses .min(32) but script_hash_bytes is only a 20-byte array. If the input script_hash has a length between 21-32 bytes, this will panic at runtime.

Apply this diff to fix the bounds check:

     pub fn new_p2sh(script_hash: Vec<u8>) -> Self {
         let mut script_hash_bytes = [0u8; 20];
         let bytes = script_hash.as_slice();
-        let len = bytes.len().min(32);
+        let len = bytes.len().min(20);
         script_hash_bytes[..len].copy_from_slice(&bytes[..len]);
 
         let mut bytes = vec![
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn new_p2sh(script_hash: Vec<u8>) -> Self {
let mut script_hash_bytes = [0u8; 20];
let bytes = script_hash.as_slice();
let len = bytes.len().min(32);
script_hash[..len].copy_from_slice(&bytes[..len]);
script_hash_bytes[..len].copy_from_slice(&bytes[..len]);
let mut bytes = vec![
opcodes::all::OP_HASH160.to_u8(),
opcodes::all::OP_PUSHBYTES_20.to_u8(),
];
bytes.extend_from_slice(&script_hash);
bytes.extend_from_slice(&script_hash_bytes);
bytes.push(opcodes::all::OP_EQUAL.to_u8());
Self::from_bytes(bytes)
}
pub fn new_p2sh(script_hash: Vec<u8>) -> Self {
let mut script_hash_bytes = [0u8; 20];
let bytes = script_hash.as_slice();
let len = bytes.len().min(20);
script_hash_bytes[..len].copy_from_slice(&bytes[..len]);
let mut bytes = vec![
opcodes::all::OP_HASH160.to_u8(),
opcodes::all::OP_PUSHBYTES_20.to_u8(),
];
bytes.extend_from_slice(&script_hash_bytes);
bytes.push(opcodes::all::OP_EQUAL.to_u8());
Self::from_bytes(bytes)
}
🤖 Prompt for AI Agents
In packages/wasm-dpp2/src/core_script.rs around lines 55 to 68, the code sets
script_hash_bytes as a 20-byte array but calculates len with .min(32), which can
cause a panic when script_hash is 21–32 bytes; change the length cap to 20 (or
use script_hash_bytes.len()) before copy_from_slice so you only copy up to the
20 bytes available, then proceed to build the P2SH byte vector and call
Self::from_bytes(bytes).


#[wasm_bindgen(js_name = "toAddress")]
pub fn to_address(&self, js_network: &JsValue) -> WasmDppResult<String> {
let network = NetworkWasm::try_from(js_network.clone())?;
pub fn to_address(
&self,
#[wasm_bindgen(unchecked_param_type = "Network | string")] network: &JsValue,
) -> WasmDppResult<String> {
let network_wasm = NetworkWasm::try_from(network.clone())?;

let payload = Payload::from_script(self.0.as_script())
.map_err(|err| WasmDppError::invalid_argument(err.to_string()))?;

let address = Address::new(network.into(), payload);
let address = Address::new(network_wasm.into(), payload);

Ok(address.to_string())
}
Expand All @@ -94,7 +97,7 @@ impl CoreScriptWasm {
encode(self.0.to_bytes().as_slice(), Hex)
}

#[wasm_bindgen(js_name = "base64")]
#[wasm_bindgen(js_name = "toBase64")]
pub fn to_base64(&self) -> String {
encode(self.0.to_bytes().as_slice(), Base64)
}
Expand Down
47 changes: 38 additions & 9 deletions packages/wasm-dpp2/src/data_contract/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use dpp::serialization::{
};
use dpp::version::PlatformVersion;
use js_sys::{Object, Reflect};
use serde_json::Value as JsonValue;
use std::collections::BTreeMap;
use wasm_bindgen::JsValue;
use wasm_bindgen::prelude::wasm_bindgen;
Expand Down Expand Up @@ -108,7 +109,7 @@ impl DataContractWasm {

let owner_id: IdentifierWasm = js_owner_id.clone().try_into()?;

let owner_id_value = Value::from(owner_id.get_base58());
let owner_id_value = Value::from(owner_id.to_base58());

let schema: Value = serde_wasm_bindgen::from_value(js_schema)
.map_err(|err| WasmDppError::serialization(err.to_string()))?;
Expand Down Expand Up @@ -196,8 +197,8 @@ impl DataContractWasm {
Ok(DataContractWasm(data_contract_with_tokens))
}

#[wasm_bindgen(js_name = "fromValue")]
pub fn from_value(
#[wasm_bindgen(js_name = "fromJSON")]
pub fn from_json(
js_value: JsValue,
full_validation: bool,
js_platform_version: JsValue,
Expand All @@ -207,9 +208,37 @@ impl DataContractWasm {
false => PlatformVersionWasm::try_from(js_platform_version)?,
};

let value = js_value.with_serde_to_platform_value()?;
let json_value: JsonValue = serde_wasm_bindgen::from_value(js_value).map_err(|err| {
WasmDppError::serialization(format!(
"unable to deserialize JSON value for DataContract.fromJSON: {}",
err
))
})?;

let contract = DataContract::from_value(value, full_validation, &platform_version.into())?;
let contract =
DataContract::from_json(json_value, full_validation, &platform_version.into())
.map_err(WasmDppError::from)?;

Ok(DataContractWasm(contract))
}

#[wasm_bindgen(js_name = "fromObject")]
pub fn from_object(
js_value: JsValue,
full_validation: bool,
js_platform_version: JsValue,
) -> WasmDppResult<DataContractWasm> {
let platform_version = match js_platform_version.is_undefined() {
true => PlatformVersionWasm::default(),
false => PlatformVersionWasm::try_from(js_platform_version)?,
};

let json_value: JsonValue = serde_wasm_bindgen::from_value(js_value)
.map_err(|err| WasmDppError::serialization(err.to_string()))?;

let contract =
DataContract::from_json(json_value, full_validation, &platform_version.into())
.map_err(WasmDppError::from)?;

Ok(DataContractWasm(contract))
}
Expand Down Expand Up @@ -275,22 +304,22 @@ impl DataContractWasm {
Ok(encode(self.to_bytes(js_platform_version)?.as_slice(), Hex))
}

#[wasm_bindgen(js_name = "base64")]
#[wasm_bindgen(js_name = "toBase64")]
pub fn to_base64(&self, js_platform_version: JsValue) -> WasmDppResult<String> {
Ok(encode(
self.to_bytes(js_platform_version)?.as_slice(),
Base64,
))
}

#[wasm_bindgen(js_name = "toValue")]
pub fn to_value(&self, js_platform_version: JsValue) -> WasmDppResult<JsValue> {
#[wasm_bindgen(js_name = "toObject")]
pub fn to_object(&self, js_platform_version: JsValue) -> WasmDppResult<JsValue> {
let platform_version = match js_platform_version.is_undefined() {
true => PlatformVersionWasm::default(),
false => PlatformVersionWasm::try_from(js_platform_version)?,
};

let serializer = serde_wasm_bindgen::Serializer::json_compatible();
let serializer = serde_wasm_bindgen::Serializer::default();

self.0
.clone()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl DataContractCreateTransitionWasm {
Ok(encode(self.to_bytes()?.as_slice(), Hex))
}

#[wasm_bindgen(js_name = "base64")]
#[wasm_bindgen(js_name = "toBase64")]
pub fn to_base64(&self) -> WasmDppResult<String> {
Ok(encode(self.to_bytes()?.as_slice(), Base64))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl DataContractUpdateTransitionWasm {
Ok(encode(self.to_bytes()?.as_slice(), Hex))
}

#[wasm_bindgen(js_name = "base64")]
#[wasm_bindgen(js_name = "toBase64")]
pub fn to_base64(&self) -> WasmDppResult<String> {
Ok(encode(self.to_bytes()?.as_slice(), Base64))
}
Expand Down
6 changes: 3 additions & 3 deletions packages/wasm-dpp2/src/epoch/finalized_epoch_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,9 @@ impl FinalizedEpochInfoWasm {
}

#[wasm_bindgen(setter = "blockProposers")]
pub fn set_block_proposers(&mut self, js_block_proposers: &JsValue) -> WasmDppResult<()> {
let block_proposers = block_proposers_from_js(js_block_proposers)?;
self.v0_mut().block_proposers = block_proposers;
pub fn set_block_proposers(&mut self, block_proposers: &JsValue) -> WasmDppResult<()> {
let block_proposers_map = block_proposers_from_js(block_proposers)?;
self.v0_mut().block_proposers = block_proposers_map;
Ok(())
}

Expand Down
12 changes: 6 additions & 6 deletions packages/wasm-dpp2/src/identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,18 @@ impl IdentifierWasm {
#[wasm_bindgen(constructor)]
pub fn new(
#[wasm_bindgen(unchecked_param_type = "Identifier | Uint8Array | string")]
js_identifier: &JsValue,
identifier: &JsValue,
) -> WasmDppResult<IdentifierWasm> {
IdentifierWasm::try_from(js_identifier)
IdentifierWasm::try_from(identifier)
}

#[wasm_bindgen(js_name = "base58")]
pub fn get_base58(&self) -> String {
#[wasm_bindgen(js_name = "toBase58")]
pub fn to_base58(&self) -> String {
self.0.to_string(Base58)
}

#[wasm_bindgen(js_name = "base64")]
pub fn get_base64(&self) -> String {
#[wasm_bindgen(js_name = "toBase64")]
pub fn to_base64(&self) -> String {
self.0.to_string(Base64)
}

Expand Down
Loading
Loading