Skip to content

Conversation

QuantumExplorer
Copy link
Member

@QuantumExplorer QuantumExplorer commented Jul 30, 2025

Issue being fixed or feature implemented

What was done?

How Has This Been Tested?

Breaking Changes

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

Summary by CodeRabbit

  • New Features

    • Integrated a new WebAssembly SDK (wasm-sdk) into the platform, enabling improved performance and additional blockchain operations.
    • Added an adapter to seamlessly delegate identity, document, data contract, and name operations to the wasm-sdk when available.
    • Introduced npm scripts for targeted and full builds, and updated package exports for better module access.
  • Bug Fixes

    • Improved handling of wallet synchronization and UTXO availability in test environments.
    • Enhanced error handling and fallback logic for operations involving the wasm-sdk.
  • Documentation

    • Added detailed guidance and troubleshooting for wasm-sdk integration and test suite setup.
    • Documented known issues, environment requirements, and migration notes for developers and testers.
  • Refactor

    • Updated platform client methods to conditionally use the wasm-sdk, preserving legacy logic as fallback.
    • Introduced a compatibility layer to support legacy test flows during migration.
  • Chores

    • Updated dependency management to include the wasm-sdk as an optional, locally linked package.
    • Adjusted TypeScript build configuration to exclude specific JavaScript loader files.

quantum and others added 2 commits July 29, 2025 18:17
- Replace DPP with wasm-sdk for all platform methods
- Add WasmPlatformAdapter for wasm-sdk integration
- Update all identity, document, contract, and name methods
- Add compatibility layer for platform test suite
- Fix createAssetLockProof to handle undefined dpp
- Document test suite issues and findings

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

coderabbitai bot commented Jul 30, 2025

Walkthrough

This change integrates the @dashevo/wasm-sdk into the js-dash-sdk platform client. It introduces a new adapter for the wasm-sdk, conditionally delegates platform methods to the wasm-sdk, updates configuration and documentation, and adds compatibility layers for legacy DPP interfaces. Several platform methods now support both wasm-sdk and legacy flows, with extensive refactoring and new TypeScript type definitions.

Changes

Cohort / File(s) Change Summary
Platform Class Refactor & Adapter Integration
packages/js-dash-sdk/src/SDK/Client/Platform/Platform.ts, packages/js-dash-sdk/src/SDK/Client/Platform/adapters/WasmPlatformAdapter.ts, packages/js-dash-sdk/src/SDK/Client/Platform/adapters/wasm-sdk-loader.js, packages/js-dash-sdk/src/SDK/Client/Platform/types/wasm-sdk.d.ts
Refactored Platform class to use a new WasmPlatformAdapter, added loader for wasm-sdk ES module, introduced TypeScript types for wasm-sdk, and provided platform enable/disable control.
Platform Methods: wasm-sdk Delegation
packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/get.ts, .../contracts/history.ts, .../contracts/publish.ts, .../contracts/update.ts, .../documents/broadcast.ts, .../documents/get.ts, .../identities/creditTransfer.ts, .../identities/creditWithdrawal.ts, .../identities/get.ts, .../identities/register.ts, .../identities/topUp.ts, .../identities/update.ts, .../names/register.ts, .../names/resolveByRecord.ts, .../names/search.ts, .../broadcastStateTransition.ts
Added conditional delegation to wasm-sdk for contract, document, identity, and name methods. Legacy logic retained as fallback.
Configuration & Build
.pnp.cjs, packages/js-dash-sdk/package.json, packages/js-dash-sdk/tsconfig.build.json
Added wasm-sdk as dependency, updated exports, scripts, and build exclusions.
Documentation & Test Suite Guidance
CLAUDE.md, packages/platform-test-suite/WASM_SDK_TEST_ISSUES.md
Added sections and new file documenting wasm-sdk integration, test suite issues, and troubleshooting.
Test Suite Compatibility Layer
packages/platform-test-suite/lib/test/wasm-sdk-compat.js
Added a shim to provide legacy DPP interface over wasm-sdk for tests, with patching utility.
Test Suite Minor Formatting
packages/platform-test-suite/lib/test/createClientWithFundedWallet.js, .../createFaucetClient.js
Added blank lines before return statements; no logic changes.

Sequence Diagram(s)

sequenceDiagram
    participant App
    participant Platform
    participant WasmAdapter
    participant WasmSdk

    App->>Platform: Call platform method (e.g., publish, get, update)
    alt wasmSdk available and enabled
        Platform->>WasmAdapter: Delegate call (convert params)
        WasmAdapter->>WasmSdk: Call wasm-sdk method
        WasmSdk-->>WasmAdapter: Return result
        WasmAdapter-->>Platform: Convert and return result
        Platform-->>App: Return result
    else legacy fallback
        Platform->>Platform: Use legacy DPP logic
        Platform-->>App: Return result
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

enhancement, js-sdk

Suggested reviewers

  • shumkov

Poem

In the warren where code bunnies dwell,
A wasm wind begins to swell—
Adapters hop and Platform leaps,
Old DPP softly, quietly sleeps.
Now docs and tests all join the fun,
Dash hops ahead—migration begun!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/changeToWasmSDKForJSSDK

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

♻️ Duplicate comments (2)
packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/update.ts (2)

22-24: Same non-null assertion issue as in broadcast.ts.


65-65: Critical: Inconsistent return types between execution paths.

Similar to broadcast.ts, this method returns different types:

  • wasm-sdk path: result object from wasm-sdk
  • legacy path: dataContractUpdateTransition

Also applies to: 101-101

🧹 Nitpick comments (23)
packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/get.ts (1)

53-60: Extract contract caching logic to reduce duplication.

The contract caching logic is duplicated between the wasm-sdk and legacy paths. Consider extracting this into a helper method.

+  private cacheContract(contractId: Identifier, contract: any) {
+    for (const appName of this.client.getApps().getNames()) {
+      const appDefinition = this.client.getApps().get(appName);
+      if (appDefinition.contractId.equals(contractId)) {
+        appDefinition.contract = contract;
+      }
+    }
+  }

Then use this.cacheContract(contractId, contract) in both paths.

Also applies to: 90-97

packages/js-dash-sdk/src/SDK/Client/Platform/broadcastStateTransition.ts (1)

41-43: Extract hash computation to reduce duplication.

The SHA-256 hash computation for the state transition is duplicated between the wasm-sdk and legacy paths.

+  const computeStateTransitionHash = (stateTransition: any): Buffer => {
+    return crypto.createHash('sha256')
+      .update(stateTransition.toBuffer())
+      .digest();
+  };

  // In wasm-sdk path:
-  const hash = crypto.createHash('sha256')
-    .update(stateTransition.toBuffer())
-    .digest();
+  const hash = computeStateTransitionHash(stateTransition);

  // In legacy path:
-  const hash = crypto.createHash('sha256')
-    .update(stateTransition.toBuffer())
-    .digest();
+  const hash = computeStateTransitionHash(stateTransition);

Also applies to: 97-99

packages/js-dash-sdk/src/SDK/Client/Platform/methods/names/search.ts (1)

14-36: Consider adding caching for consistency.

Unlike the contracts get method, this search method doesn't implement caching for wasm-sdk results. Consider whether caching would be beneficial for name searches.

packages/js-dash-sdk/src/SDK/Client/Platform/methods/names/register.ts (1)

50-52: Simplify records serialization.

The records object conversion is unnecessarily complex. Consider simplifying the JSON serialization.

-    const recordsJson = JSON.stringify({
-      identity: records.identity ? Identifier.from(records.identity).toString() : undefined,
-    });
+    const recordsJson = JSON.stringify({
+      ...records,
+      identity: records.identity ? Identifier.from(records.identity).toString() : records.identity,
+    });
packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/get.ts (1)

17-41: Good wasm-sdk integration pattern with room for error handling improvements.

The conditional delegation approach is well-structured and maintains backward compatibility. The caching strategy is a smart performance optimization.

However, consider these improvements:

  1. Error handling robustness: Line 36 relies on string matching for error detection which could be fragile across different error formats.

  2. Type safety: The id.toString() call assumes the toString() method exists but doesn't handle potential conversion failures.

Consider enhancing error handling:

-    } catch (e) {
-      if (e.message?.includes('not found') || e.message?.includes('does not exist')) {
-        return null;
-      }
-      throw e;
-    }
+    } catch (e) {
+      // Handle known not-found patterns and specific error types
+      if (e.message?.toLowerCase().includes('not found') || 
+          e.message?.toLowerCase().includes('does not exist') ||
+          e.code === 'IDENTITY_NOT_FOUND') {
+        return null;
+      }
+      throw e;
+    }
CLAUDE.md (1)

132-149: Valuable documentation addition with minor style fixes needed.

This documentation provides essential troubleshooting guidance for wasm-sdk integration testing.

Apply these style fixes:

-1. **Faucet Wallet Setup**: The faucet wallet needs funded UTXOs. Generate blocks to the faucet address:
+1. **Faucet Wallet Setup**: The faucet wallet needs to be funded with UTXOs. Generate blocks to the faucet address:
-   - Bootstrap.js maps FAUCET_1_* vars to FAUCET_* based on worker ID
+   - Bootstrap.js maps FAUCET_1_* vars to FAUCET_* based on worker ID
packages/js-dash-sdk/src/SDK/Client/Platform/methods/names/resolveByRecord.ts (1)

12-43: Well-structured wasm-sdk delegation with thoughtful value conversion.

The implementation correctly handles different record types and includes helpful debug logging.

Consider these improvements:

  1. Value conversion safety: Lines 20-21 use generic toString() which could fail for objects without this method.

  2. Hardcoded parameter: Line 30 hardcodes parentDomainName as undefined. Consider if this should be configurable.

Enhance value conversion safety:

-    } else if (typeof value === 'object' && value.toString) {
-      recordValue = value.toString();
+    } else if (typeof value === 'object' && value && typeof value.toString === 'function') {
+      recordValue = value.toString();
+    } else if (typeof value === 'object') {
+      recordValue = JSON.stringify(value);
packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/topUp.ts (1)

41-64: Solid wasm-sdk delegation with adapter-based conversions.

The use of adapter methods for format conversions maintains good separation of concerns.

Consider adding error handling for adapter conversions:

+    try {
       // Convert asset lock proof to hex format for wasm-sdk
       const assetLockProofHex = adapter.convertAssetLockProof(assetLockProof);
       
       // Convert private key to WIF format
       const assetLockPrivateKeyWIF = adapter.convertPrivateKeyToWIF(assetLockPrivateKey);
+    } catch (conversionError) {
+      this.logger.error(`[Identity#topUp] Conversion error: ${conversionError.message}`);
+      throw new Error(`Failed to convert parameters for wasm-sdk: ${conversionError.message}`);
+    }

Also, consider validating the success response format:

-    return result.success !== false;
+    return Boolean(result?.success);
packages/platform-test-suite/lib/test/wasm-sdk-compat.js (1)

11-67: Excellent compatibility layer design with defensive buffer handling.

The approach of checking for legacy DPP first and providing a shim otherwise is elegant. The buffer conversion logic is appropriately defensive.

Consider these minor improvements:

  1. More specific error messages: Lines 49, 56, 63 could provide more context about what needs to be implemented.

  2. Validation: Consider validating that required platform utility methods exist.

Enhance error messages with more context:

-        throw new Error('createFromBuffer not yet implemented for wasm-sdk compatibility');
+        throw new Error('Identity.createFromBuffer not yet implemented for wasm-sdk compatibility. ' +
+                       'This method needs to convert wasm-sdk identity responses to DPP format.');
packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/history.ts (2)

67-72: Consider more specific error detection

The error handling checks for "not found" or "does not exist" in the message. Consider checking for specific error types or codes if the wasm-sdk provides them, as string matching on error messages can be fragile.


26-26: Improve return type definition

The function returns Promise<any> but actually returns a specific structure { [key: number]: DataContract }. Consider defining a proper return type for better type safety.

-): Promise<any> {
+): Promise<{ [key: number]: DataContract } | null> {
packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/update.ts (1)

70-83: Consider more explicit success check

The success check result.success !== false would return true for undefined or null values. Consider a more explicit check.

-    return result.success !== false;
+    return result.success === true;
packages/js-dash-sdk/src/SDK/Client/Platform/methods/documents/broadcast.ts (3)

32-35: Consider avoiding the non-null assertion operator for better type safety.

While the non-null assertion is safe here due to the check on line 33, consider restructuring to avoid using !:

-  if (this.wasmSdk && this.getAdapter()) {
-    const adapter = this.getAdapter()!;
+  const adapter = this.getAdapter();
+  if (this.wasmSdk && adapter) {

40-41: Add error handling for HD key retrieval.

The getIdentityHDKeyById call could potentially fail if the identity doesn't exist in the wallet. Consider adding error handling:

+    try {
       const { privateKey: documentPrivateKey } = account.identities
         .getIdentityHDKeyById(identity.getId().toString(), 1);
+    } catch (error) {
+      throw new Error(`Failed to retrieve document private key for identity ${identity.getId()}: ${error.message}`);
+    }

133-146: Consider extracting cache management logic to reduce duplication.

The cache acknowledgment logic is duplicated between the wasm-sdk path and legacy path. Consider extracting it to a helper method:

+  // Helper method for cache management
+  const manageCacheForDocuments = (documents: {
+    create?: ExtendedDocument[],
+    delete?: ExtendedDocument[]
+  }) => {
+    if (documents.create) {
+      documents.create.forEach((document) => {
+        const documentLocator = `${document.getDataContractId().toString()}/${document.getType()}`;
+        this.fetcher.acknowledgeKey(documentLocator);
+      });
+    }
+    
+    if (documents.delete) {
+      documents.delete.forEach((document) => {
+        const documentLocator = `${document.getDataContractId().toString()}/${document.getType()}`;
+        this.fetcher.forgetKey(documentLocator);
+      });
+    }
+  };

   // In wasm-sdk path:
-  // Handle document acknowledgment for cache
-  if (documents.create) {
-    documents.create.forEach((document) => {
-      const documentLocator = `${document.getDataContractId().toString()}/${document.getType()}`;
-      this.fetcher.acknowledgeKey(documentLocator);
-    });
-  }
-  
-  if (documents.delete) {
-    documents.delete.forEach((document) => {
-      const documentLocator = `${document.getDataContractId().toString()}/${document.getType()}`;
-      this.fetcher.forgetKey(documentLocator);
-    });
-  }
+  manageCacheForDocuments(documents);

   // In legacy path:
-  // Acknowledge documents identifiers to handle retry attempts to mitigate
-  // state transition propagation lag
-  if (documents.create) {
-    documents.create.forEach((document) => {
-      const documentLocator = `${document.getDataContractId().toString()}/${document.getType()}`;
-      this.fetcher.acknowledgeKey(documentLocator);
-    });
-  }
-
-  // Forget documents identifiers to not retry on them anymore
-  if (documents.delete) {
-    documents.delete.forEach((document) => {
-      const documentLocator = `${document.getDataContractId().toString()}/${document.getType()}`;
-      this.fetcher.forgetKey(documentLocator);
-    });
-  }
+  manageCacheForDocuments(documents);

Also applies to: 186-200

packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/update.ts (1)

54-61: Extract duplicated app update logic.

The app update logic is duplicated between wasm-sdk and legacy paths. Consider extracting to a helper:

+  // Helper to update apps with the new contract
+  const updateAppsWithContract = (updatedContract: any) => {
+    for (const appName of this.client.getApps().getNames()) {
+      const appDefinition = this.client.getApps().get(appName);
+      if (appDefinition.contractId.equals(updatedContract.getId()) && appDefinition.contract) {
+        appDefinition.contract = updatedContract;
+      }
+    }
+  };

   // In wasm-sdk path:
-  // Update app with updated data contract if available
-  // eslint-disable-next-line
-  for (const appName of this.client.getApps().getNames()) {
-    const appDefinition = this.client.getApps().get(appName);
-    if (appDefinition.contractId.equals(updatedDataContract.getId()) && appDefinition.contract) {
-      appDefinition.contract = updatedDataContract;
-    }
-  }
+  updateAppsWithContract(updatedDataContract);

   // In legacy path:
-  // Update app with updated data contract if available
-  // eslint-disable-next-line
-  for (const appName of this.client.getApps().getNames()) {
-    const appDefinition = this.client.getApps().get(appName);
-    if (appDefinition.contractId.equals(updatedDataContract.getId()) && appDefinition.contract) {
-      appDefinition.contract = updatedDataContract;
-    }
-  }
+  updateAppsWithContract(updatedDataContract);

Also applies to: 91-98

packages/js-dash-sdk/package.json (1)

134-136: Consider the implications of using a local file path for the wasm-sdk dependency.

Using "file:../wasm-sdk/pkg" has several implications:

  1. Requires wasm-sdk to be built locally before installing js-dash-sdk
  2. Won't work for external consumers installing from npm
  3. May cause issues in CI/CD environments

Consider:

  • Publishing @dashevo/wasm-sdk to npm (even as a pre-release)
  • Using a git URL with a specific commit/tag
  • Documenting the build requirements clearly
packages/platform-test-suite/WASM_SDK_TEST_ISSUES.md (1)

83-83: Clarify which platform method files were modified

The documentation mentions "Various platform method files - Migrated to use wasm-sdk" but doesn't specify which files. Consider listing the specific files or file patterns for better traceability.

packages/js-dash-sdk/src/SDK/Client/Platform/adapters/WasmPlatformAdapter.ts (2)

114-118: Complete regtest network configuration

The TODO comment indicates that regtest/local networks need custom URL configuration but currently fall back to testnet, which could cause connection issues.

Would you like me to implement proper regtest network configuration that accepts custom DAPI URLs from the constructor?


205-208: Add error logging for DPP conversion failures

When DPP identity creation fails, the error is silently caught. Consider logging the error to help debug compatibility issues during migration.

 } catch (e) {
+  console.debug('Failed to convert identity using DPP, falling back to raw object:', e);
   // Fallback to raw object if DPP creation fails
   return wasmIdentity;
 }
packages/js-dash-sdk/src/SDK/Client/Platform/Platform.ts (2)

116-117: Document the deprecation timeline for legacy DPP

The comment indicates DPP will be removed once migration is complete, but there's no timeline or migration guide. Consider adding more specific deprecation information.

-// Legacy DPP - will be removed once migration is complete
+// Legacy DPP - deprecated, will be removed in v4.0.0
+// Migration guide: https://docs.dash.org/sdk/migration/wasm-sdk
 dpp?: any;

266-271: Add error handling to dispose method

The dispose method should handle potential errors during adapter disposal to ensure cleanup completes even if adapter disposal fails.

 async dispose(): Promise<void> {
   if (this.adapter) {
-    await this.adapter.dispose();
+    try {
+      await this.adapter.dispose();
+    } catch (error) {
+      this.logger.error('Error disposing adapter:', error);
+    }
   }
   this.wasmSdk = undefined;
 }
packages/js-dash-sdk/src/SDK/Client/Platform/types/wasm-sdk.d.ts (1)

14-17: Document the numeric enum values

The numeric values for type, purpose, and securityLevel should reference the actual enum names for better maintainability.

 export interface IdentityPublicKey {
   id: number;
-  type: number; // 0 = ECDSA_SECP256K1, 1 = BLS12_381, 2 = ECDSA_HASH160
-  purpose: number; // 0 = AUTHENTICATION, 1 = ENCRYPTION, 2 = DECRYPTION, 3 = TRANSFER
-  securityLevel: number; // 0 = MASTER, 1 = CRITICAL, 2 = HIGH, 3 = MEDIUM
+  type: number; // KeyType: 0 = ECDSA_SECP256K1, 1 = BLS12_381, 2 = ECDSA_HASH160
+  purpose: number; // KeyPurpose: 0 = AUTHENTICATION, 1 = ENCRYPTION, 2 = DECRYPTION, 3 = TRANSFER
+  securityLevel: number; // SecurityLevel: 0 = MASTER, 1 = CRITICAL, 2 = HIGH, 3 = MEDIUM
   data: string; // Base64-encoded public key
   readOnly: boolean;
 }

Comment on lines +3067 to +3074
["@dashevo/wasm-sdk", [\
["file:../wasm-sdk/pkg#../wasm-sdk/pkg::hash=944b57&locator=dash%40workspace%3Apackages%2Fjs-dash-sdk", {\
"packageLocation": "./.yarn/cache/@dashevo-wasm-sdk-file-7f6fe61b82-1ccf5cd50c.zip/node_modules/@dashevo/wasm-sdk/",\
"packageDependencies": [\
["@dashevo/wasm-sdk", "file:../wasm-sdk/pkg#../wasm-sdk/pkg::hash=944b57&locator=dash%40workspace%3Apackages%2Fjs-dash-sdk"]\
],\
"linkType": "HARD"\
}]\
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

Avoid committing the auto-generated .pnp.cjs file

.pnp.cjs is regenerated every time yarn install runs and is highly environment-specific. Keeping it under version control:

• Bloats the diff and repository size
• Causes constant merge conflicts between branches
• Risks leaking absolute cache paths that break on other machines

Move .pnp.cjs (and the accompanying .pnp.loader.mjs) to .gitignore and drop it from the PR; rely on yarn install to recreate it in CI/dev environments.

🤖 Prompt for AI Agents
In the .pnp.cjs file around lines 3067 to 3074, the issue is that this
auto-generated file should not be committed to version control because it is
environment-specific and causes repository bloat, merge conflicts, and potential
path leaks. To fix this, remove .pnp.cjs and .pnp.loader.mjs from the PR, add
both files to the .gitignore file to prevent future commits, and rely on running
yarn install to regenerate them in development and CI environments.

@@ -8572,6 +8581,7 @@
["@dashevo/masternode-reward-shares-contract", "workspace:packages/masternode-reward-shares-contract"],\
["@dashevo/wallet-lib", "workspace:packages/wallet-lib"],\
["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\
["@dashevo/wasm-sdk", "file:../wasm-sdk/pkg#../wasm-sdk/pkg::hash=944b57&locator=dash%40workspace%3Apackages%2Fjs-dash-sdk"],\
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Workspace dependency should be declared in package.json, not patched via PnP state

The extra entry that injects @dashevo/wasm-sdk as a file:../wasm-sdk/pkg dependency belongs in packages/js-dash-sdk/package.json (e.g. "@dashevo/wasm-sdk": "workspace:*").
Editing/committing PnP runtime state is brittle—any subsequent yarn install will overwrite these lines. Please ensure the dependency is declared in the proper manifest and let Yarn regenerate .pnp.cjs automatically.

🤖 Prompt for AI Agents
In the .pnp.cjs file at line 8584, the dependency on @dashevo/wasm-sdk is
incorrectly patched directly in the PnP runtime state. Remove this manual patch
from .pnp.cjs and instead declare "@dashevo/wasm-sdk": "workspace:*" as a
dependency in the packages/js-dash-sdk/package.json file. Then run yarn install
to regenerate the .pnp.cjs file automatically with the correct workspace
dependency.

// Node.js environment - use initSync with buffer
const fs = require('fs');
const path = require('path');
const wasmPath = path.join(__dirname, '..', '..', '..', '..', '..', '..', '..', '.yarn', 'cache', '@dashevo-wasm-sdk-file-7f6fe61b82-1ccf5cd50c.zip', 'node_modules', '@dashevo', 'wasm-sdk', 'wasm_sdk_bg.wasm');
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

Avoid hardcoded WASM file path

The hardcoded path to the WASM file in the Yarn cache is brittle and will break if the package version or cache structure changes. This path construction is highly specific to the current Yarn PnP setup.

Consider using a more robust approach:

-const wasmPath = path.join(__dirname, '..', '..', '..', '..', '..', '..', '..', '.yarn', 'cache', '@dashevo-wasm-sdk-file-7f6fe61b82-1ccf5cd50c.zip', 'node_modules', '@dashevo', 'wasm-sdk', 'wasm_sdk_bg.wasm');
+// Use require.resolve to find the wasm file relative to the wasm-sdk package
+const wasmSdkPath = require.resolve('@dashevo/wasm-sdk/package.json');
+const wasmPath = path.join(path.dirname(wasmSdkPath), 'wasm_sdk_bg.wasm');
📝 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
const wasmPath = path.join(__dirname, '..', '..', '..', '..', '..', '..', '..', '.yarn', 'cache', '@dashevo-wasm-sdk-file-7f6fe61b82-1ccf5cd50c.zip', 'node_modules', '@dashevo', 'wasm-sdk', 'wasm_sdk_bg.wasm');
// Use require.resolve to find the wasm file relative to the wasm-sdk package
const wasmSdkPath = require.resolve('@dashevo/wasm-sdk/package.json');
const wasmPath = path.join(path.dirname(wasmSdkPath), 'wasm_sdk_bg.wasm');
🤖 Prompt for AI Agents
In packages/js-dash-sdk/src/SDK/Client/Platform/adapters/WasmPlatformAdapter.ts
at line 68, the WASM file path is hardcoded with deep relative paths pointing to
the Yarn cache, which is fragile and prone to breakage with version or structure
changes. Replace this hardcoded path by dynamically resolving the WASM file
location using package resolution methods such as require.resolve or importing
the path from the package's metadata, ensuring the path adapts to different
environments and package versions.

Comment on lines +135 to +145
convertAssetLockProof(assetLock: any): string {
// Convert asset lock from js-dash-sdk format to wasm-sdk hex format
const proofObject = {
type: assetLock.type || 0,
transaction: assetLock.transaction.toString('hex'),
outputIndex: assetLock.outputIndex,
instantLock: assetLock.instantLock ? assetLock.instantLock.toString('hex') : undefined,
};

return JSON.stringify(proofObject);
}
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

Inconsistent return format in convertAssetLockProof

The method comment mentions converting to "wasm-sdk hex format" but the implementation returns a JSON string. Either update the comment or the implementation to match the expected format.

🤖 Prompt for AI Agents
In packages/js-dash-sdk/src/SDK/Client/Platform/adapters/WasmPlatformAdapter.ts
around lines 135 to 145, the method convertAssetLockProof's comment states it
returns a wasm-sdk hex format, but it actually returns a JSON string. To fix
this, either update the comment to accurately describe that the method returns a
JSON string representation of the proof object or modify the implementation to
return the asset lock proof in the expected wasm-sdk hex format, ensuring
consistency between the comment and the code.

Comment on lines +42 to +43
const wasmAdapter = adapter as any;
return await wasmAdapter.wasmSdk.data_contract_fetch(sdk, contractIdString);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove unsafe type assertion.

The type assertion as any bypasses TypeScript's type safety. Consider properly typing the adapter or using a more specific interface.

-      const wasmAdapter = adapter as any;
-      return await wasmAdapter.wasmSdk.data_contract_fetch(sdk, contractIdString);
+      return await adapter.wasmSdk.data_contract_fetch(sdk, contractIdString);
📝 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
const wasmAdapter = adapter as any;
return await wasmAdapter.wasmSdk.data_contract_fetch(sdk, contractIdString);
return await adapter.wasmSdk.data_contract_fetch(sdk, contractIdString);
🤖 Prompt for AI Agents
In packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/get.ts at
lines 42-43, remove the unsafe type assertion 'as any' on the adapter variable.
Instead, define or import a proper TypeScript interface that accurately
describes the adapter's structure, especially the wasmSdk property and its
data_contract_fetch method, and use that interface to type the adapter variable.
This will restore type safety and avoid bypassing TypeScript's checks.

}));

const documentsJson = JSON.stringify(documentsData);
const putType = documents.replace?.includes(docs[0]) ? 'replace' : 'create';
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: Incorrect put type determination for mixed document groups.

The current logic only checks if the first document in a group is a replacement, but a group could contain both create and replace operations for the same contract/type combination. This would cause all documents in the group to be treated with the same operation type.

Consider processing create and replace operations separately:

-          const putType = documents.replace?.includes(docs[0]) ? 'replace' : 'create';
+          // Process create and replace operations separately
+          const createDocs = docs.filter(doc => documents.create?.includes(doc));
+          const replaceDocs = docs.filter(doc => documents.replace?.includes(doc));
+          
+          if (createDocs.length > 0) {
+            // Process create operations
+            const result = await this.wasmSdk.documentsPut(
+              dataContractId,
+              documentType,
+              JSON.stringify(createDocs.map(doc => ({
+                id: doc.getId()?.toString(),
+                data: doc.getData(),
+                createdAt: doc.getCreatedAt(),
+                updatedAt: doc.getUpdatedAt(),
+              }))),
+              identityHex,
+              privateKeyWIF,
+              'create'
+            );
+            results.push(result);
+          }
+          
+          if (replaceDocs.length > 0) {
+            // Process replace operations
+            const result = await this.wasmSdk.documentsPut(
+              dataContractId,
+              documentType,
+              JSON.stringify(replaceDocs.map(doc => ({
+                id: doc.getId()?.toString(),
+                data: doc.getData(),
+                createdAt: doc.getCreatedAt(),
+                updatedAt: doc.getUpdatedAt(),
+              }))),
+              identityHex,
+              privateKeyWIF,
+              'replace'
+            );
+            results.push(result);
+          }
📝 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
const putType = documents.replace?.includes(docs[0]) ? 'replace' : 'create';
- const putType = documents.replace?.includes(docs[0]) ? 'replace' : 'create';
+ // Process create and replace operations separately
+ const createDocs = docs.filter(doc => documents.create?.includes(doc));
+ const replaceDocs = docs.filter(doc => documents.replace?.includes(doc));
+
+ if (createDocs.length > 0) {
+ // Process create operations
+ const result = await this.wasmSdk.documentsPut(
+ dataContractId,
+ documentType,
+ JSON.stringify(createDocs.map(doc => ({
+ id: doc.getId()?.toString(),
+ data: doc.getData(),
+ createdAt: doc.getCreatedAt(),
+ updatedAt: doc.getUpdatedAt(),
+ }))),
+ identityHex,
+ privateKeyWIF,
+ 'create'
+ );
+ results.push(result);
+ }
+
+ if (replaceDocs.length > 0) {
+ // Process replace operations
+ const result = await this.wasmSdk.documentsPut(
+ dataContractId,
+ documentType,
+ JSON.stringify(replaceDocs.map(doc => ({
+ id: doc.getId()?.toString(),
+ data: doc.getData(),
+ createdAt: doc.getCreatedAt(),
+ updatedAt: doc.getUpdatedAt(),
+ }))),
+ identityHex,
+ privateKeyWIF,
+ 'replace'
+ );
+ results.push(result);
+ }
🤖 Prompt for AI Agents
In packages/js-dash-sdk/src/SDK/Client/Platform/methods/documents/broadcast.ts
at line 84, the current logic determines the putType based only on the first
document, which fails for mixed groups containing both create and replace
operations. To fix this, separate the documents into two groups: one for create
operations and one for replace operations, then process each group independently
to ensure correct handling of each operation type.

});

// Return the results
return results;
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Critical: Inconsistent return types between wasm-sdk and legacy paths.

The function returns different types:

  • wasm-sdk path: array of results
  • legacy path: documentsBatchTransition object

This inconsistency will break code that depends on the return value.

Also applies to: 208-208


🏁 Script executed:

#!/bin/bash
# Description: Find all usages of broadcast method to understand expected return type

# Search for broadcast method calls
rg -A 5 "\.broadcast\(" --glob "*.ts" --glob "*.js" | grep -v "test" | head -20

# Search for type definitions or interfaces that might define the expected return type
ast-grep --pattern 'broadcast($_): $_'

Length of output: 1178


🏁 Script executed:

#!/bin/bash
set -e

# Display relevant portion around wasm-sdk return
sed -n '140,165p' packages/js-dash-sdk/src/SDK/Client/Platform/methods/documents/broadcast.ts

# Display relevant portion around legacy return
sed -n '200,225p' packages/js-dash-sdk/src/SDK/Client/Platform/methods/documents/broadcast.ts

Length of output: 1118


Fix Required: Unify broadcast return type

The broadcast method in
packages/js-dash-sdk/src/SDK/Client/Platform/methods/documents/broadcast.ts
returns two different types depending on the code path:

  • Lines 148–153 (wasm-sdk path):
    // …returns an array of wasm-sdk results
    return results; // DppDocumentsBroadcastResponse[]
  • Lines 221–225 (legacy DPP path):
    // …returns a single DocumentsBatchTransition
    return documentsBatchTransition; // DocumentsBatchTransition

This mismatch will break callers expecting a consistent payload.

Recommendations:

  • Update the method signature to reflect a union return type, e.g.
    public async broadcast(
      documents: DocumentBatch,
      identity: Identity,
    ): Promise<DppDocumentsBroadcastResponse[] | DocumentsBatchTransition> {  }
  • Or—preferably—normalize both branches to return the same shape (e.g. always an array), wrapping the legacy documentsBatchTransition in a one-item array.
  • Adjust any downstream type definitions and documentation to match the new return type.

Please apply these changes to ensure callers can rely on a single, consistent return type.

🤖 Prompt for AI Agents
In packages/js-dash-sdk/src/SDK/Client/Platform/methods/documents/broadcast.ts
at line 153 and around lines 221-225, the broadcast method returns inconsistent
types: an array of DppDocumentsBroadcastResponse in the wasm-sdk path and a
single DocumentsBatchTransition in the legacy DPP path. To fix this, update the
method to always return the same type by wrapping the legacy
DocumentsBatchTransition return value in a one-item array, ensuring both paths
return an array. Also, update the method signature to reflect this consistent
array return type and adjust any related type definitions and documentation
accordingly.

Comment on lines +125 to +154
// Convert startAt/startAfter
let startAt = opts.startAt;
let startAfter = opts.startAfter;

if (startAt instanceof ExtendedDocument) {
startAt = startAt.getId().toString();
} else if (typeof startAt === 'string') {
startAt = Identifier.from(startAt).toString();
} else if (startAt && typeof startAt === 'object') {
startAt = startAt.toString();
}

if (startAfter instanceof ExtendedDocument) {
startAfter = startAfter.getId().toString();
} else if (typeof startAfter === 'string') {
startAfter = Identifier.from(startAfter).toString();
} else if (startAfter && typeof startAfter === 'object') {
startAfter = startAfter.toString();
}

// Call wasm-sdk getDocuments
const result = await this.wasmSdk.getDocuments(
appDefinition.contractId.toString(),
fieldType,
whereClause,
orderByClause,
opts.limit,
startAt ? parseInt(startAt as string) : undefined,
startAfter ? parseInt(startAfter as string) : undefined
);
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: Incorrect identifier to integer conversion

The code converts startAt and startAfter to identifier strings (lines 130-143) but then attempts to parse them as integers (lines 152-153). Identifier strings are not numeric values and parseInt will likely return NaN or incorrect values.

The wasm-sdk likely expects the identifier strings directly, not parsed as integers:

-        startAt ? parseInt(startAt as string) : undefined,
-        startAfter ? parseInt(startAfter as string) : undefined
+        startAt as string | undefined,
+        startAfter as string | undefined
🤖 Prompt for AI Agents
In packages/js-dash-sdk/src/SDK/Client/Platform/methods/documents/get.ts around
lines 125 to 154, the code converts startAt and startAfter to identifier strings
but then incorrectly parses them as integers before passing to
wasmSdk.getDocuments. Remove the parseInt calls and pass startAt and startAfter
directly as strings to the getDocuments method, ensuring the identifiers are
used correctly without numeric conversion.


this.logger.debug(`[Identity#creditTransfer] Transferred ${amount} credits from ${identity.getId().toString()} to ${recipientId.toString()}`);

return result.success !== false;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Simplify return value logic and add null check.

The double negative result.success !== false is confusing and doesn't handle undefined/null cases properly:

-    return result.success !== false;
+    return result.success === true;

Or if the API can return undefined:

-    return result.success !== false;
+    return result.success ?? false;
📝 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
return result.success !== false;
return result.success ?? false;
🤖 Prompt for AI Agents
In
packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/creditTransfer.ts
at line 44, simplify the return statement by directly returning a boolean that
checks if result.success is truthy, and add a null or undefined check for result
to avoid runtime errors. Replace the current double negative logic with a
clearer expression that safely handles cases where result or result.success
might be undefined or null.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant