diff --git a/.github/grpc-queries-cache.json b/.github/grpc-queries-cache.json index 33fa12dbe1c..ed3e6d2954a 100644 --- a/.github/grpc-queries-cache.json +++ b/.github/grpc-queries-cache.json @@ -116,7 +116,7 @@ "status": "implemented" }, "getTokenContractInfo": { - "status": "not_implemented" + "status": "implemented" }, "getTokenPreProgrammedDistributions": { "status": "not_implemented" @@ -143,5 +143,5 @@ "status": "not_implemented" } }, - "last_updated": "2025-01-06T00:00:00Z" + "last_updated": "2025-07-14T03:27:11.465612" } \ No newline at end of file diff --git a/.github/scripts/check-grpc-coverage.py b/.github/scripts/check-grpc-coverage.py index 97c9adf351f..62681b849e7 100755 --- a/.github/scripts/check-grpc-coverage.py +++ b/.github/scripts/check-grpc-coverage.py @@ -170,6 +170,28 @@ def save_cache(cache_file, cache_data): json.dump(cache_data, f, indent=2) +def check_wasm_sdk_documentation(): + """Check WASM SDK documentation completeness""" + wasm_sdk_path = Path(__file__).parent.parent.parent / 'packages' / 'wasm-sdk' + check_script = wasm_sdk_path / 'check_documentation.py' + + if not check_script.exists(): + return True, [] # Skip if WASM SDK doesn't have the check script + + # Run the documentation check + import subprocess + result = subprocess.run(['python3', str(check_script)], cwd=wasm_sdk_path, capture_output=True, text=True) + + # Parse the output to find errors + errors = [] + if result.returncode != 0: + output_lines = result.stdout.strip().split('\n') + for line in output_lines: + if line.startswith('ERROR:'): + errors.append(line) + + return result.returncode == 0, errors + def main(): """Main function to check gRPC coverage.""" # Get paths @@ -313,12 +335,29 @@ def main(): print("\n" + report_content) - # Exit with error only if there are missing NEW queries - if missing_new_queries: - print(f"\nERROR: {len(missing_new_queries)} NEW queries are not implemented in rs-sdk") + # Check WASM SDK documentation + print("\n" + "=" * 80) + print("Checking WASM SDK Documentation...") + print("=" * 80) + + wasm_docs_ok, wasm_errors = check_wasm_sdk_documentation() + + if wasm_docs_ok: + print("✅ WASM SDK documentation is up to date") + else: + print(f"❌ WASM SDK documentation has {len(wasm_errors)} errors:") + for error in wasm_errors: + print(f" {error}") + print("\nTo fix WASM SDK documentation errors, run:") + print(" cd packages/wasm-sdk && python3 generate_docs.py") + + # Exit with error if there are missing NEW queries or documentation errors + if missing_new_queries or not wasm_docs_ok: + if missing_new_queries: + print(f"\nERROR: {len(missing_new_queries)} NEW queries are not implemented in rs-sdk") sys.exit(1) else: - print("\nSUCCESS: All NEW gRPC queries are implemented in rs-sdk (or excluded)") + print("\nSUCCESS: All NEW gRPC queries are implemented in rs-sdk (or excluded) and documentation is up to date") sys.exit(0) diff --git a/.github/workflows/wasm-sdk-documentation-check.yml b/.github/workflows/wasm-sdk-documentation-check.yml new file mode 100644 index 00000000000..a77d22c559b --- /dev/null +++ b/.github/workflows/wasm-sdk-documentation-check.yml @@ -0,0 +1,152 @@ +name: Check WASM SDK Documentation + +on: + workflow_dispatch: + pull_request: + paths: + - 'packages/wasm-sdk/index.html' + - 'packages/wasm-sdk/docs.html' + - 'packages/wasm-sdk/AI_REFERENCE.md' + - 'packages/wasm-sdk/docs_manifest.json' + - 'packages/wasm-sdk/generate_docs.py' + - 'packages/wasm-sdk/check_documentation.py' + - '.github/workflows/wasm-sdk-documentation-check.yml' + push: + branches: + - master + - 'v*-dev' + paths: + - 'packages/wasm-sdk/index.html' + - 'packages/wasm-sdk/docs.html' + - 'packages/wasm-sdk/AI_REFERENCE.md' + - 'packages/wasm-sdk/docs_manifest.json' + - 'packages/wasm-sdk/generate_docs.py' + - 'packages/wasm-sdk/check_documentation.py' + - '.github/workflows/wasm-sdk-documentation-check.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + check-wasm-sdk-documentation: + name: Check WASM SDK Documentation + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Check out repo + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Check documentation completeness + id: doc-check + working-directory: packages/wasm-sdk + run: | + # Run the documentation check + if python3 check_documentation.py; then + echo "status=success" >> $GITHUB_OUTPUT + else + echo "status=failure" >> $GITHUB_OUTPUT + fi + + # Note: At this point, the documentation hasn't been regenerated yet, + # so this check will only detect if the PR already includes documentation changes + if git diff --quiet HEAD -- docs.html docs_manifest.json AI_REFERENCE.md; then + echo "docs_modified=false" >> $GITHUB_OUTPUT + else + echo "docs_modified=true" >> $GITHUB_OUTPUT + fi + + - name: Upload documentation check report + if: always() + uses: actions/upload-artifact@v4 + with: + name: documentation-check-report + path: packages/wasm-sdk/documentation-check-report.txt + + - name: Comment PR + if: github.event_name == 'pull_request' && steps.doc-check.outputs.status == 'failure' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const reportPath = 'packages/wasm-sdk/documentation-check-report.txt'; + + if (fs.existsSync(reportPath)) { + const report = fs.readFileSync(reportPath, 'utf8'); + const status = '${{ steps.doc-check.outputs.status }}' === 'success' ? '✅' : '❌'; + + // Find existing comment + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + const botComment = comments.find(comment => + comment.user.type === 'Bot' && + comment.body.includes('WASM SDK Documentation Check') + ); + + const body = `### ${status} WASM SDK Documentation Check\n\n\`\`\`\n${report}\n\`\`\`\n\n**To fix documentation issues:**\n\`\`\`bash\ncd packages/wasm-sdk\npython3 generate_docs.py\n\`\`\``; + + if (botComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body: body + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: body + }); + } + } + + - name: Auto-update documentation (non-protected branches) + if: github.event_name == 'push' && !contains(github.ref, 'master') && !contains(github.ref, 'main') && steps.doc-check.outputs.status == 'failure' + working-directory: packages/wasm-sdk + run: | + # Generate updated documentation + python3 generate_docs.py + # Check if there are changes + if ! git diff --quiet docs.html docs_manifest.json AI_REFERENCE.md; then + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git add docs.html docs_manifest.json AI_REFERENCE.md + git commit -m "chore: update WASM SDK documentation [skip ci]" + git push + fi + + - name: Create documentation update PR (protected branches) + if: github.event_name == 'push' && (contains(github.ref, 'master') || contains(github.ref, 'main')) && steps.doc-check.outputs.status == 'failure' + uses: peter-evans/create-pull-request@v5 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "chore: update WASM SDK documentation" + title: "chore: update WASM SDK documentation" + body: | + This PR updates the WASM SDK documentation to match the current implementation. + + Auto-generated by GitHub Actions. + branch: auto-update-wasm-docs-${{ github.run_number }} + base: ${{ github.ref_name }} + path: packages/wasm-sdk + + - name: Fail if documentation is out of date + if: steps.doc-check.outputs.status == 'failure' && github.event_name == 'pull_request' + run: | + echo "Documentation is out of date. Please run 'python3 generate_docs.py' in packages/wasm-sdk/" + exit 1 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8c3806b7365..6d8b24ae784 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,10 @@ packages/wasm-sdk/.cargo/ packages/wasm-sdk/pkg/ packages/wasm-sdk/dist/ packages/wasm-sdk/*.bak +packages/wasm-sdk/wasm_sdk.js +packages/wasm-sdk/wasm_sdk_bg.wasm +packages/wasm-sdk/documentation-check-report.txt +packages/wasm-sdk/extracted_definitions.json # gRPC coverage report grpc-coverage-report.txt diff --git a/CLAUDE.md b/CLAUDE.md index ccaf6a1c3f8..2c6a306e558 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -97,6 +97,8 @@ yarn configure:tests:network **SDK** (`packages/js-dash-sdk`, `packages/rs-sdk`): Client libraries providing high-level interfaces for building applications on Dash Platform. +**WASM SDK** (`packages/wasm-sdk`): WebAssembly bindings for browser-based applications. See [AI_REFERENCE.md](packages/wasm-sdk/AI_REFERENCE.md) for comprehensive API documentation. + **Dashmate** (`packages/dashmate`): Node management tool for setting up and managing Dash Platform nodes. ### Data Contracts @@ -114,6 +116,10 @@ Platform uses data contracts to define application data schemas: 2. **Cross-language Integration**: WASM bindings connect Rust and JavaScript code 3. **Local Development**: Docker Compose environment managed by dashmate 4. **Testing**: Comprehensive test suites at unit, integration, and e2e levels +5. **WASM SDK Development**: + - Build with `./build.sh` in `packages/wasm-sdk` + - Test with web interface at `index.html` + - Keep docs in sync: `python3 generate_docs.py` ### Important Patterns diff --git a/packages/wasm-sdk/.gitignore b/packages/wasm-sdk/.gitignore deleted file mode 100644 index 03314f77b5a..00000000000 --- a/packages/wasm-sdk/.gitignore +++ /dev/null @@ -1 +0,0 @@ -Cargo.lock diff --git a/packages/wasm-sdk/AI_REFERENCE.md b/packages/wasm-sdk/AI_REFERENCE.md new file mode 100644 index 00000000000..fb5cab7a8aa --- /dev/null +++ b/packages/wasm-sdk/AI_REFERENCE.md @@ -0,0 +1,1139 @@ +# Dash Platform WASM JS SDK - AI Reference + +## Overview +The Dash Platform WASM JS SDK provides WebAssembly bindings for interacting with Dash Platform from JavaScript/TypeScript. This reference is optimized for AI understanding and quick implementation. + +## Quick Setup +```javascript +// Import and initialize +import init, { WasmSdk } from './pkg/wasm_sdk.js'; + +await init(); +const transport = { + url: "https://52.12.176.90:1443/", // testnet + network: "testnet" +}; +const proofs = true; // Enable proof verification +const sdk = await WasmSdk.new(transport, proofs); +``` + +## Authentication +Most state transitions require authentication: +```javascript +const identityHex = "hex_encoded_identity"; +const privateKeyHex = "hex_encoded_private_key"; +``` + +## Query Operations + +### Pattern +All queries follow this pattern: +```javascript +const result = await sdk.{query_name}(param1, param2, ...); +``` + +### Available Queries + +#### Identity Queries + +**Get Identity** - `getIdentity` +*Fetch an identity by its identifier* + +Parameters: +- `id` (text, required) - Identity ID + +Example: +```javascript +const identity = await sdk.getIdentity("GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec"); +``` + +**Get Identity Keys** - `getIdentityKeys` +*Retrieve keys associated with an identity* + +Parameters: +- `identityId` (text, required) - Identity ID +- `keyRequestType` (select, optional) - Key Request Type + - Options: `all` (All Keys (AllKeys {}) - Get all keys for the identity), `specific` (Specific Keys (SpecificKeys with key_ids) - Get specific keys by ID [🚧 Work in Progress]), `search` (Search Keys (SearchKey with purpose_map) - Search by purpose and security level [🚧 Work in Progress]) +- `specificKeyIds` (array, optional) - Specific Key IDs (required for 'specific' type) + - Example: `0,1,2` +- `searchPurposeMap` (text, optional) - Search Purpose Map JSON (required for 'search' type) + - Example: `{"0": {"0": "current"}, "1": {"0": "all"}}` + +Example: +```javascript +const result = await sdk.getIdentityKeys("identityId"); +``` + +**Get Identities Contract Keys** - `getIdentitiesContractKeys` +*Get keys for multiple identities related to a specific contract* + +Parameters: +- `identitiesIds` (array, required) - Identity IDs +- `contractId` (text, required) - Contract ID +- `documentTypeName` (text, optional) - Document Type (optional) +- `keyRequestType` (select, optional) - Key Request Type + +Example: +```javascript +const result = await sdk.getIdentitiesContractKeys([], "contractId"); +``` + +**Get Identity Nonce** - `getIdentityNonce` +*Get the current nonce for an identity* + +Parameters: +- `identityId` (text, required) - Identity ID + +Example: +```javascript +const result = await sdk.getIdentityNonce("identityId"); +``` + +**Get Identity Contract Nonce** - `getIdentityContractNonce` +*Get the nonce for an identity in relation to a specific contract* + +Parameters: +- `identityId` (text, required) - Identity ID +- `contractId` (text, required) - Contract ID + +Example: +```javascript +const result = await sdk.getIdentityContractNonce("identityId", "contractId"); +``` + +**Get Identity Balance** - `getIdentityBalance` +*Get the credit balance of an identity* + +Parameters: +- `id` (text, required) - Identity ID + +Example: +```javascript +const balance = await sdk.getIdentityBalance(identityId); +``` + +**Get Identities Balances** - `getIdentitiesBalances` +*Get balances for multiple identities* + +Parameters: +- `identityIds` (array, required) - Identity IDs + +Example: +```javascript +const result = await sdk.getIdentitiesBalances([]); +``` + +**Get Identity Balance and Revision** - `getIdentityBalanceAndRevision` +*Get both balance and revision number for an identity* + +Parameters: +- `id` (text, required) - Identity ID + +Example: +```javascript +const result = await sdk.getIdentityBalanceAndRevision("id"); +``` + +**Get Identity by Unique Public Key Hash** - `getIdentityByPublicKeyHash` +*Find an identity by its unique public key hash* + +Parameters: +- `publicKeyHash` (text, required) - Public Key Hash + - Example: `b7e904ce25ed97594e72f7af0e66f298031c1754` + +Example: +```javascript +const result = await sdk.getIdentityByPublicKeyHash("publicKeyHash"); +``` + +**Get Identity by Non-Unique Public Key Hash** - `getIdentityByNonUniquePublicKeyHash` +*Find identities by non-unique public key hash* + +Parameters: +- `publicKeyHash` (text, required) - Public Key Hash + - Example: `518038dc858461bcee90478fd994bba8057b7531` + +Example: +```javascript +const result = await sdk.getIdentityByNonUniquePublicKeyHash("publicKeyHash"); +``` + +**Get Identity Token Balances** - `getIdentityTokenBalances` +*Get token balances for an identity* + +Parameters: +- `identityId` (text, required) - Identity ID +- `tokenIds` (array, required) - Token IDs + +Example: +```javascript +const result = await sdk.getIdentityTokenBalances("identityId", []); +``` + +**Get Identities Token Balances** - `getIdentitiesTokenBalances` +*Get token balance for multiple identities* + +Parameters: +- `identityIds` (array, required) - Identity IDs +- `tokenId` (text, required) - Token ID + - Example: `Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv` + +Example: +```javascript +const result = await sdk.getIdentitiesTokenBalances([], "tokenId"); +``` + +**Get Identity Token Info** - `getIdentityTokenInfos` +*Get token information for an identity's tokens* + +Parameters: +- `identityId` (text, required) - Identity ID +- `tokenIds` (array, optional) - Token IDs (optional) + - Example: `["Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv"]` + +Example: +```javascript +const result = await sdk.getIdentityTokenInfos("identityId"); +``` + +**Get Identities Token Info** - `getIdentitiesTokenInfos` +*Get token information for multiple identities with a specific token* + +Parameters: +- `identityIds` (array, required) - Identity IDs +- `tokenId` (text, required) - Token ID + - Example: `Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv` + +Example: +```javascript +const result = await sdk.getIdentitiesTokenInfos([], "tokenId"); +``` + +#### Data Contract Queries + +**Get Data Contract** - `getDataContract` +*Fetch a data contract by its identifier* + +Parameters: +- `id` (text, required) - Data Contract ID + - Example: `GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec` + +Example: +```javascript +const result = await sdk.getDataContract("id"); +``` + +**Get Data Contract History** - `getDataContractHistory` +*Get the version history of a data contract* + +Parameters: +- `id` (text, required) - Data Contract ID + - Example: `GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec` +- `limit` (number, optional) - Limit +- `offset` (number, optional) - Offset + +Example: +```javascript +const result = await sdk.getDataContractHistory("id"); +``` + +**Get Data Contracts** - `getDataContracts` +*Fetch multiple data contracts by their identifiers* + +Parameters: +- `ids` (array, required) - Data Contract IDs + - Example: `["GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec", "ALybvzfcCwMs7sinDwmtumw17NneuW7RgFtFHgjKmF3A"]` + +Example: +```javascript +const result = await sdk.getDataContracts([]); +``` + +#### Document Queries + +**Get Documents** - `getDocuments` +*Query documents from a data contract* + +Parameters: +- `dataContractId` (text, required) - Data Contract ID + - Example: `GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec` +- `documentType` (text, required) - Document Type + - Example: `domain` +- `whereClause` (text, optional) - Where Clause (JSON) + - Example: `[["normalizedParentDomainName", "==", "dash"], ["normalizedLabel", "==", "therea1s11mshaddy5"]]` +- `orderBy` (text, optional) - Order By (JSON) + - Example: `[["$createdAt", "desc"]]` +- `limit` (number, optional) - Limit + +Example: +```javascript +const docs = await sdk.getDocuments( + contractId, + "note", + JSON.stringify([["$ownerId", "==", identityId]]), + JSON.stringify([["$createdAt", "desc"]]), + 10 +); +``` + +**Get Document** - `getDocument` +*Fetch a specific document by ID* + +Parameters: +- `dataContractId` (text, required) - Data Contract ID + - Example: `GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec` +- `documentType` (text, required) - Document Type + - Example: `domain` +- `documentId` (text, required) - Document ID + - Example: `7NYmEKQsYtniQRUmxwdPGeVcirMoPh5ZPyAKz8BWFy3r` + +Example: +```javascript +const result = await sdk.getDocument("dataContractId", "documentType", "documentId"); +``` + +#### DPNS Queries + +**Get DPNS Usernames** - `getDpnsUsername` +*Get DPNS usernames for an identity* + +Parameters: +- `identityId` (text, required) - Identity ID + +Example: +```javascript +const result = await sdk.getDpnsUsername("identityId"); +``` + +**DPNS Check Availability** - `dpnsCheckAvailability` +*Check if a DPNS username is available* + +Parameters: +- `label` (text, required) - Label (Username) + +Example: +```javascript +const result = await sdk.dpnsCheckAvailability("label"); +``` + +**DPNS Resolve Name** - `dpnsResolve` +*Resolve a DPNS name to an identity ID* + +Parameters: +- `name` (text, required) - Name + +Example: +```javascript +const result = await sdk.dpnsResolve("name"); +``` + +#### Voting & Contested Resources + +**Get Contested Resources** - `getContestedResources` +*Get list of contested resources* + +Parameters: +- `resultType` (select, required) - Result Type +- `documentTypeName` (text, required) - Document Type +- `indexName` (text, required) - Index Name +- `count` (number, optional) - Count + +Example: +```javascript +const result = await sdk.getContestedResources("resultType", "documentTypeName", "indexName"); +``` + +**Get Contested Resource Vote State** - `getContestedResourceVoteState` +*Get the current vote state for a contested resource* + +Parameters: +- `contractId` (text, required) - Contract ID +- `documentTypeName` (text, required) - Document Type +- `indexName` (text, required) - Index Name + +Example: +```javascript +const result = await sdk.getContestedResourceVoteState("contractId", "documentTypeName", "indexName"); +``` + +**Get Contested Resource Voters for Identity** - `getContestedResourceVotersForIdentity` +*Get voters who voted for a specific identity in a contested resource* + +Parameters: +- `contractId` (text, required) - Contract ID +- `documentTypeName` (text, required) - Document Type +- `indexName` (text, required) - Index Name +- `contestantId` (text, required) - Contestant Identity ID + +Example: +```javascript +const result = await sdk.getContestedResourceVotersForIdentity("contractId", "documentTypeName", "indexName", "contestantId"); +``` + +**Get Contested Resource Identity Votes** - `getContestedResourceIdentityVotes` +*Get all votes cast by a specific identity* + +Parameters: +- `identityId` (text, required) - Identity ID + +Example: +```javascript +const result = await sdk.getContestedResourceIdentityVotes("identityId"); +``` + +**Get Vote Polls by End Date** - `getVotePollsByEndDate` +*Get vote polls within a time range* + +Parameters: +- `startTimeMs` (number, required) - Start Time (ms) +- `endTimeMs` (number, required) - End Time (ms) + +Example: +```javascript +const result = await sdk.getVotePollsByEndDate(100, 100); +``` + +#### Protocol & Version + +**Get Protocol Version Upgrade State** - `getProtocolVersionUpgradeState` +*Get the current state of protocol version upgrades* + +No parameters required. + +Example: +```javascript +const result = await sdk.getProtocolVersionUpgradeState(); +``` + +**Get Protocol Version Upgrade Vote Status** - `getProtocolVersionUpgradeVoteStatus` +*Get voting status for protocol version upgrades* + +Parameters: +- `startProTxHash` (text, required) - Start ProTx Hash + - Example: `143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113` +- `count` (number, required) - Count + +Example: +```javascript +const result = await sdk.getProtocolVersionUpgradeVoteStatus("startProTxHash", 100); +``` + +#### Epoch & Block + +**Get Epochs Info** - `getEpochsInfo` +*Get information about epochs* + +Parameters: +- `epoch` (number, required) - Start Epoch +- `count` (number, required) - Count +- `ascending` (checkbox, optional) - Ascending Order + +Example: +```javascript +const result = await sdk.getEpochsInfo(100, 100); +``` + +**Get Current Epoch** - `getCurrentEpoch` +*Get information about the current epoch* + +No parameters required. + +Example: +```javascript +const result = await sdk.getCurrentEpoch(); +``` + +**Get Finalized Epoch Info** - `getFinalizedEpochInfos` +*Get information about finalized epochs* + +Parameters: +- `startEpoch` (number, required) - Start Epoch +- `count` (number, required) - Count + +Example: +```javascript +const result = await sdk.getFinalizedEpochInfos(100, 100); +``` + +**Get Evonodes Proposed Epoch Blocks by IDs** - `getEvonodesProposedEpochBlocksByIds` +*Get proposed blocks by evonode IDs* + +Parameters: +- `ids` (array, required) - ProTx Hashes + - Example: `["143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113"]` + +Example: +```javascript +const result = await sdk.getEvonodesProposedEpochBlocksByIds([]); +``` + +**Get Evonodes Proposed Epoch Blocks by Range** - `getEvonodesProposedEpochBlocksByRange` +*Get proposed blocks by range* + +Parameters: +- `startProTxHash` (text, required) - Start ProTx Hash + - Example: `143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113` +- `count` (number, required) - Count + +Example: +```javascript +const result = await sdk.getEvonodesProposedEpochBlocksByRange("startProTxHash", 100); +``` + +#### Token Queries + +**Get Token Statuses** - `getTokenStatuses` +*Get token statuses* + +Parameters: +- `tokenIds` (array, required) - Token IDs + +Example: +```javascript +const result = await sdk.getTokenStatuses([]); +``` + +**Get Token Direct Purchase Prices** - `getTokenDirectPurchasePrices` +*Get direct purchase prices for tokens* + +Parameters: +- `tokenIds` (array, required) - Token IDs + +Example: +```javascript +const result = await sdk.getTokenDirectPurchasePrices([]); +``` + +**Get Token Contract Info** - `getTokenContractInfo` +*Get information about a token contract* + +Parameters: +- `dataContractId` (text, required) - Data Contract ID + - Example: `EETVvWgohFDKtbB3ejEzBcDRMNYkc9TtgXY6y8hzP3Ta` + +Example: +```javascript +const result = await sdk.getTokenContractInfo("dataContractId"); +``` + +**Get Token Perpetual Distribution Last Claim** - `getTokenPerpetualDistributionLastClaim` +*Get last claim information for perpetual distribution* + +Parameters: +- `identityId` (text, required) - Identity ID +- `tokenId` (text, required) - Token ID + +Example: +```javascript +const result = await sdk.getTokenPerpetualDistributionLastClaim("identityId", "tokenId"); +``` + +**Get Token Total Supply** - `getTokenTotalSupply` +*Get total supply of a token* + +Parameters: +- `tokenId` (text, required) - Token ID + - Example: `Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv` + +Example: +```javascript +const result = await sdk.getTokenTotalSupply("tokenId"); +``` + +#### Group Queries + +**Get Group Info** - `getGroupInfo` +*Get information about a group* + +Parameters: +- `contractId` (text, required) - Contract ID +- `groupContractPosition` (number, required) - Group Contract Position + +Example: +```javascript +const result = await sdk.getGroupInfo("contractId", 100); +``` + +**Get Group Infos** - `getGroupInfos` +*Get information about multiple groups* + +Parameters: +- `contractId` (text, required) - Contract ID +- `startAtGroupContractPosition` (number, optional) - Start at Position +- `startGroupContractPositionIncluded` (checkbox, optional) - Include Start Position +- `count` (number, optional) - Count + +Example: +```javascript +const result = await sdk.getGroupInfos("contractId"); +``` + +**Get Group Actions** - `getGroupActions` +*Get actions for a group* + +Parameters: +- `contractId` (text, required) - Contract ID +- `groupContractPosition` (number, required) - Group Contract Position +- `status` (select, required) - Status + - Options: `ACTIVE` (Active), `CLOSED` (Closed) +- `startActionId` (text, optional) - Start Action ID +- `startActionIdIncluded` (checkbox, optional) - Include Start Action +- `count` (number, optional) - Count + +Example: +```javascript +const result = await sdk.getGroupActions("contractId", 100, "status"); +``` + +**Get Group Action Signers** - `getGroupActionSigners` +*Get signers for a group action* + +Parameters: +- `contractId` (text, required) - Contract ID +- `groupContractPosition` (number, required) - Group Contract Position +- `status` (select, required) - Status + - Options: `ACTIVE` (Active), `CLOSED` (Closed) +- `actionId` (text, required) - Action ID + +Example: +```javascript +const result = await sdk.getGroupActionSigners("contractId", 100, "status", "actionId"); +``` + +#### System & Utility + +**Get Status** - `getStatus` +*Get system status* + +No parameters required. + +Example: +```javascript +const result = await sdk.getStatus(); +``` + +**Get Current Quorums Info** - `getCurrentQuorumsInfo` +*Get information about current quorums* + +No parameters required. + +Example: +```javascript +const result = await sdk.getCurrentQuorumsInfo(); +``` + +**Get Prefunded Specialized Balance** - `getPrefundedSpecializedBalance` +*Get prefunded specialized balance* + +Parameters: +- `identityId` (text, required) - Specialized Balance ID + - Example: `AzaU7zqCT7X1kxh8yWxkT9PxAgNqWDu4Gz13emwcRyAT` + +Example: +```javascript +const result = await sdk.getPrefundedSpecializedBalance("identityId"); +``` + +**Get Total Credits in Platform** - `getTotalCreditsInPlatform` +*Get total credits in the platform* + +No parameters required. + +Example: +```javascript +const result = await sdk.getTotalCreditsInPlatform(); +``` + +**Get Path Elements** - `getPathElements` +*Access any data in the Dash Platform state tree. This low-level query allows direct access to GroveDB storage by specifying a path through the tree structure and keys to retrieve at that path. Common paths include: Identities (32), Tokens (96), DataContractDocuments (64), Balances (16), Votes (80), and more.* + +Parameters: +- `path` (array, required) - Path +- `keys` (array, required) - Keys + +Example: +```javascript +// Access any data in the Dash Platform state tree +// Common root paths: +// - DataContractDocuments: 64 +// - Identities: 32 +// - UniquePublicKeyHashesToIdentities: 24 +// - NonUniquePublicKeyKeyHashesToIdentities: 8 +// - Tokens: 16 +// - Pools: 48 +// - PreFundedSpecializedBalances: 40 +// - SpentAssetLockTransactions: 72 +// - WithdrawalTransactions: 80 +// - GroupActions: 88 +// - Balances: 96 +// - Misc: 104 +// - Votes: 112 +// - Versions: 120 + +// Example: Get identity balance +const result = await sdk.getPathElements(['96'], ['identityId']); + +// Example: Get identity info +const identityKeys = await sdk.getPathElements(['32'], ['identityId']); + +// Example: Get contract documents +const documents = await sdk.getPathElements(['64'], ['contractId', '1', 'documentType']); +``` + +**Wait for State Transition Result** - `waitForStateTransitionResult` +*Internal query to wait for and retrieve the result of a previously submitted state transition* + +Parameters: +- `stateTransitionHash` (text, required) - State Transition Hash + +Example: +```javascript +const result = await sdk.waitForStateTransitionResult("stateTransitionHash"); +``` + +## State Transition Operations + +### Pattern +All state transitions require authentication and follow this pattern: +```javascript +const result = await sdk.{transition_name}(identityHex, ...params, privateKeyHex); +``` + +### Available State Transitions + +#### Identity Transitions + +**Identity Create** - `identityCreate` +*Create a new identity with initial credits* + +Parameters (in addition to identity/key): +- `publicKeys` (keyArray, required) - Public Keys +- `assetLockProof` (assetLockProof, required) - Asset Lock Proof + +Example: +```javascript +const result = await sdk.identityCreate(identityHex, /* params */, privateKeyHex); +``` + +**Identity Top Up** - `identityTopUp` +*Add credits to an existing identity* + +Parameters (in addition to identity/key): +- `assetLockProof` (assetLockProof, required) - Asset Lock Proof + +Example: +```javascript +const result = await sdk.identityTopUp(identityHex, /* params */, privateKeyHex); +``` + +**Identity Update** - `identityUpdate` +*Update identity keys (add or disable)* + +Parameters (in addition to identity/key): +- `addPublicKeys` (textarea, optional) - Keys to Add (JSON array) + - Example: `[{"keyType":"ECDSA_HASH160","purpose":"AUTHENTICATION","data":"base64_key_data"}]` +- `disablePublicKeys` (text, optional) - Key IDs to Disable (comma-separated) + - Example: `2,3,5` + +Example: +```javascript +const result = await sdk.identityUpdate(identityHex, /* params */, privateKeyHex); +``` + +**Identity Credit Transfer** - `identityCreditTransfer` +*Transfer credits between identities* + +Parameters (in addition to identity/key): +- `recipientId` (text, required) - Recipient Identity ID +- `amount` (number, required) - Amount (credits) + +Example: +```javascript +const result = await sdk.identityCreditTransfer(identityHex, /* params */, privateKeyHex); +``` + +**Identity Credit Withdrawal** - `identityCreditWithdrawal` +*Withdraw credits from identity to Dash address* + +Parameters (in addition to identity/key): +- `toAddress` (text, required) - Dash Address +- `amount` (number, required) - Amount (credits) +- `coreFeePerByte` (number, optional) - Core Fee Per Byte (optional) + +Example: +```javascript +const result = await sdk.identityCreditWithdrawal(identityHex, /* params */, privateKeyHex); +``` + +#### Data Contract Transitions + +**Data Contract Create** - `dataContractCreate` +*Create a new data contract* + +Parameters (in addition to identity/key): +- `canBeDeleted` (checkbox, optional) - Can Be Deleted +- `readonly` (checkbox, optional) - Read Only +- `keepsHistory` (checkbox, optional) - Keeps History +- `documentsKeepHistoryContractDefault` (checkbox, optional) - Documents Keep History (Default) +- `documentsMutableContractDefault` (checkbox, optional) - Documents Mutable (Default) +- `documentsCanBeDeletedContractDefault` (checkbox, optional) - Documents Can Be Deleted (Default) +- `requiresIdentityEncryptionBoundedKey` (text, optional) - Requires Identity Encryption Key (optional) +- `requiresIdentityDecryptionBoundedKey` (text, optional) - Requires Identity Decryption Key (optional) +- `documentSchemas` (json, required) - Document Schemas JSON + - Example: `{ + "note": { + "type": "object", + "properties": { + "message": { + "type": "string", + "maxLength": 100, + "position": 0 + } + }, + "required": ["message"], + "additionalProperties": false + } +}` +- `groups` (json, optional) - Groups (optional) + - Example: `{}` +- `tokens` (json, optional) - Tokens (optional) + - Example: `{}` +- `keywords` (text, optional) - Keywords (comma separated, optional) +- `description` (text, optional) - Description (optional) + +Example: +```javascript +const result = await sdk.dataContractCreate(identityHex, /* params */, privateKeyHex); +``` + +**Data Contract Update** - `dataContractUpdate` +*Add document types, groups, or tokens to an existing data contract* + +Parameters (in addition to identity/key): +- `dataContractId` (text, required) - Data Contract ID +- `newDocumentSchemas` (json, optional) - New Document Schemas to Add (optional) + - Example: `{ + "newType": { + "type": "object", + "properties": { + "field": { + "type": "string", + "maxLength": 100, + "position": 0 + } + }, + "required": ["field"], + "additionalProperties": false + } +}` +- `newGroups` (json, optional) - New Groups to Add (optional) + - Example: `{}` +- `newTokens` (json, optional) - New Tokens to Add (optional) + - Example: `{}` + +Example: +```javascript +const result = await sdk.dataContractUpdate(identityHex, /* params */, privateKeyHex); +``` + +#### Document Transitions + +**Document Create** - `documentCreate` +*Create a new document* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `documentType` (text, required) - Document Type +- `fetchSchema` (button, optional) - Fetch Schema +- `documentFields` (dynamic, optional) - Document Fields + +Example: +```javascript +const result = await sdk.document_create( + identityHex, + contractId, + "note", + JSON.stringify({ message: "Hello!" }), + privateKeyHex +); +``` + +**Document Replace** - `documentReplace` +*Replace an existing document* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `documentType` (text, required) - Document Type +- `documentId` (text, required) - Document ID +- `loadDocument` (button, optional) - Load Document +- `documentFields` (dynamic, optional) - Document Fields + +Example: +```javascript +const result = await sdk.documentReplace(identityHex, /* params */, privateKeyHex); +``` + +**Document Delete** - `documentDelete` +*Delete an existing document* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `documentType` (text, required) - Document Type +- `documentId` (text, required) - Document ID + +Example: +```javascript +const result = await sdk.documentDelete(identityHex, /* params */, privateKeyHex); +``` + +**Document Transfer** - `documentTransfer` +*Transfer document ownership* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `documentType` (text, required) - Document Type +- `documentId` (text, required) - Document ID +- `recipientId` (text, required) - Recipient Identity ID + +Example: +```javascript +const result = await sdk.documentTransfer(identityHex, /* params */, privateKeyHex); +``` + +**Document Purchase** - `documentPurchase` +*Purchase a document* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `documentType` (text, required) - Document Type +- `documentId` (text, required) - Document ID +- `price` (number, required) - Price (credits) + +Example: +```javascript +const result = await sdk.documentPurchase(identityHex, /* params */, privateKeyHex); +``` + +**Document Set Price** - `documentSetPrice` +*Set or update document price* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `documentType` (text, required) - Document Type +- `documentId` (text, required) - Document ID +- `price` (number, required) - Price (credits, 0 to remove) + +Example: +```javascript +const result = await sdk.documentSetPrice(identityHex, /* params */, privateKeyHex); +``` + +**DPNS Register Name** - `dpnsRegister` +*Register a new DPNS username* + +Parameters (in addition to identity/key): +- `label` (text, required) - Username + - Example: `Enter username (e.g., alice)` + +Example: +```javascript +const result = await sdk.dpnsRegister(identityHex, /* params */, privateKeyHex); +``` + +#### Token Transitions + +**Token Burn** - `tokenBurn` +*Burn tokens* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `tokenPosition` (number, required) - Token Contract Position +- `amount` (text, required) - Amount to Burn +- `keyId` (number, required) - Key ID (for signing) +- `publicNote` (text, optional) - Public Note + +Example: +```javascript +const result = await sdk.tokenBurn(identityHex, /* params */, privateKeyHex); +``` + +**Token Mint** - `tokenMint` +*Mint new tokens* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `tokenPosition` (number, required) - Token Contract Position +- `amount` (text, required) - Amount to Mint +- `keyId` (number, required) - Key ID (for signing) +- `issuedToIdentityId` (text, optional) - Issue To Identity ID +- `publicNote` (text, optional) - Public Note + +Example: +```javascript +const result = await sdk.tokenMint(identityHex, /* params */, privateKeyHex); +``` + +**Token Transfer** - `tokenTransfer` +*Transfer tokens to another identity* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `tokenId` (text, required) - Token Contract Position +- `amount` (number, required) - Amount to Transfer +- `recipientId` (text, required) - Recipient Identity ID + +Example: +```javascript +const result = await sdk.token_transfer( + identityHex, + contractId, + tokenId, + 1000000, // amount + recipientId, + privateKeyHex +); +``` + +**Token Freeze** - `tokenFreeze` +*Freeze tokens for an identity* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `tokenId` (text, required) - Token Contract Position +- `identityId` (text, required) - Identity ID to Freeze + +Example: +```javascript +const result = await sdk.tokenFreeze(identityHex, /* params */, privateKeyHex); +``` + +**Token Unfreeze** - `tokenUnfreeze` +*Unfreeze tokens for an identity* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `tokenId` (text, required) - Token Contract Position +- `identityId` (text, required) - Identity ID to Unfreeze + +Example: +```javascript +const result = await sdk.tokenUnfreeze(identityHex, /* params */, privateKeyHex); +``` + +**Token Destroy Frozen Funds** - `tokenDestroyFrozen` +*Destroy frozen tokens* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID +- `tokenId` (text, required) - Token Contract Position +- `identityId` (text, required) - Identity ID + +Example: +```javascript +const result = await sdk.tokenDestroyFrozen(identityHex, /* params */, privateKeyHex); +``` + +#### Voting Transitions + +**DPNS Username** - `dpnsUsername` +*Cast a vote for a contested DPNS username* + +Parameters (in addition to identity/key): +- `contestedUsername` (text, required) - Contested Username + - Example: `Enter the contested username (e.g., 'myusername')` +- `voteChoice` (select, required) - Vote Choice +- `targetIdentity` (text, optional) - Target Identity ID (if voting for identity) + - Example: `Identity ID to vote for` + +Example: +```javascript +const result = await sdk.dpnsUsername(identityHex, /* params */, privateKeyHex); +``` + +**Contested Resource** - `masternodeVote` +*Cast a vote for contested resources as a masternode* + +Parameters (in addition to identity/key): +- `contractId` (text, required) - Data Contract ID + - Example: `Contract ID containing the contested resource` +- `fetchContestedResources` (button, optional) - Get Contested Resources +- `contestedResourceDropdown` (dynamic, optional) - Contested Resources +- `voteChoice` (select, required) - Vote Choice +- `targetIdentity` (text, optional) - Target Identity ID (if voting for identity) + - Example: `Identity ID to vote for` + +Example: +```javascript +const result = await sdk.masternodeVote(identityHex, /* params */, privateKeyHex); +``` + +## Common Patterns + +### Error Handling +```javascript +try { + const result = await sdk.getIdentity(identityId); + console.log(result); +} catch (error) { + console.error("Query failed:", error); +} +``` + +### Working with Proofs +```javascript +// Enable proofs during SDK initialization +const sdk = await WasmSdk.new(transport, true); + +// Query with proof verification +const identityWithProof = await sdk.getIdentity(identityId); +``` + +### Document Queries with Where/OrderBy +```javascript +// Where clause format: [[field, operator, value], ...] +const whereClause = JSON.stringify([ + ["$ownerId", "==", identityId], + ["age", ">=", 18] +]); + +// OrderBy format: [[field, direction], ...] +const orderBy = JSON.stringify([ + ["$createdAt", "desc"] +]); + +const docs = await sdk.getDocuments( + contractId, + documentType, + whereClause, + orderBy, + limit +); +``` + +### Batch Operations +```javascript +// Get multiple identities +const identityIds = ["id1", "id2", "id3"]; +const balances = await sdk.getIdentitiesBalances(identityIds); +``` + +## Important Notes + +1. **Network Endpoints**: + - Testnet: `https://52.12.176.90:1443/` + - Mainnet: Update when available + +2. **Identity Format**: Identity IDs and keys should be hex-encoded strings + +3. **Credits**: All fees are paid in credits (1 credit = 1 satoshi equivalent) + +4. **Nonces**: The SDK automatically handles nonce management for state transitions + +5. **Proofs**: Enable proofs for production applications to ensure data integrity + +## Troubleshooting + +- **Connection errors**: Verify network endpoint and that SDK is initialized +- **Invalid parameters**: Check parameter types and required fields +- **Authentication failures**: Ensure correct identity/key format and key permissions +- **Query errors**: Validate contract IDs, document types, and field names exist diff --git a/packages/wasm-sdk/CLAUDE.md b/packages/wasm-sdk/CLAUDE.md index 8191e363c28..f2d9620bc8b 100644 --- a/packages/wasm-sdk/CLAUDE.md +++ b/packages/wasm-sdk/CLAUDE.md @@ -2,6 +2,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +## Documentation + +**IMPORTANT**: For comprehensive API reference and usage examples, see: +- **[AI_REFERENCE.md](AI_REFERENCE.md)** - Complete API reference with all queries and state transitions +- **[docs.html](docs.html)** - User-friendly documentation +- **[index.html](index.html)** - Live interactive demo + +When implementing WASM SDK functionality, always refer to AI_REFERENCE.md first for accurate method signatures and examples. + ## Important Notes ### Network Connectivity @@ -42,6 +51,13 @@ Run `./build.sh` to build the WASM module. Output goes to `pkg/` directory. 4. Choose operation type (queries/state transitions) 5. Fill in parameters and execute +## Documentation Maintenance + +When adding new queries or state transitions: +1. Update the definitions in `index.html` +2. Run `python3 generate_docs.py` to regenerate documentation +3. The CI will fail if documentation is out of sync + ## Common Issues 1. **"time not implemented on this platform"** - Fixed by using `js_sys::Date::now()` in WASM builds diff --git a/packages/wasm-sdk/README.md b/packages/wasm-sdk/README.md new file mode 100644 index 00000000000..2af5d43444f --- /dev/null +++ b/packages/wasm-sdk/README.md @@ -0,0 +1,145 @@ +# Dash Platform WASM JS SDK + +This package provides WebAssembly bindings for the Dash Platform SDK, allowing JavaScript and TypeScript applications in browsers to interact with Dash Platform. + +## Overview + +The WASM JS SDK provides: +- **Queries**: Read-only operations to fetch data from Dash Platform +- **State Transitions**: Write operations to modify state on Dash Platform + +## Usage + +### Quick Start + +1. Build the WASM module: + ```bash + ./build.sh + ``` + +2. Serve the demo application: + ```bash + python3 -m http.server 8888 + ``` + +3. Open http://localhost:8888 in your browser + +### Integration + +```javascript +import init, { WasmSdk } from './pkg/wasm_sdk.js'; + +// Initialize WASM module +await init(); + +// Create SDK instance +const transport = { + url: "https://52.12.176.90:1443/", // testnet + network: "testnet" +}; +const sdk = await WasmSdk.new(transport, true); // true = enable proofs + +// Example query +const identity = await sdk.get_identity("GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec"); +``` + +## Documentation + +- **[User Documentation](docs.html)**: Comprehensive guide for all queries and state transitions +- **[AI Reference](AI_REFERENCE.md)**: Quick reference optimized for AI assistants and developers +- **[Live Demo](index.html)**: Interactive interface to test all SDK functionality + +## Development + +### Building + +The SDK requires Rust and wasm-pack: + +```bash +# Install wasm-pack if not already installed +curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + +# Build the WASM module +./build.sh +``` + +### Documentation + +**IMPORTANT**: Documentation must be kept in sync with `index.html`. When adding or modifying queries/state transitions in `index.html`, you MUST update the documentation: + +```bash +# Regenerate documentation after changes to index.html +python3 generate_docs.py + +# Check if documentation is up to date +python3 check_documentation.py +``` + +The CI will fail if documentation is out of sync with the code. + +### Adding New Features + +1. Add the query/transition definition to `index.html` +2. Implement the corresponding method in the Rust code +3. Regenerate documentation: `python3 generate_docs.py` +4. Test your changes using the web interface + +### CI/CD + +This package has automated checks for: +- Documentation completeness (all queries/transitions must be documented) +- Documentation freshness (docs must be regenerated when index.html changes) + +The checks run on: +- Pull requests that modify relevant files +- Pushes to master and release branches + +## Architecture + +### File Structure + +- `src/`: Rust source code + - `queries/`: Query implementations + - `state_transitions/`: State transition implementations + - `sdk.rs`: Main SDK interface +- `index.html`: Interactive demo and test interface +- `docs.html`: User-friendly documentation +- `AI_REFERENCE.md`: Developer/AI reference documentation +- `generate_docs.py`: Documentation generator +- `check_documentation.py`: Documentation validation + +### Key Concepts + +1. **Queries**: Read operations that don't modify state + - Identity queries (balance, keys, nonce) + - Document queries (with where/orderBy support) + - Data contract queries + - Token queries + - System queries + +2. **State Transitions**: Operations that modify platform state + - Identity operations (create, update, transfer) + - Document operations (create, update, delete) + - Token operations (mint, burn, transfer) + - Voting operations + +3. **Proofs**: Cryptographic proofs can be requested for most queries to verify data authenticity + +## Testing + +The web interface (`index.html`) provides comprehensive testing capabilities: +- Network selection (mainnet/testnet) +- Query execution with parameter validation +- State transition testing with authentication +- Proof verification toggle + +## Contributing + +1. Make your changes +2. Update documentation if needed: `python3 generate_docs.py` +3. Run tests +4. Submit a pull request + +## License + +See the main platform repository for license information. \ No newline at end of file diff --git a/packages/wasm-sdk/check_documentation.py b/packages/wasm-sdk/check_documentation.py new file mode 100755 index 00000000000..d3c4ccc07b6 --- /dev/null +++ b/packages/wasm-sdk/check_documentation.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 +""" +Check that all queries and state transitions in index.html are documented +""" + +import os +import sys +import json +from pathlib import Path +from datetime import datetime + +def check_documentation_completeness(): + """Check if documentation is up to date with index.html""" + + script_dir = Path(__file__).parent + + # Required files + index_file = script_dir / 'index.html' + manifest_file = script_dir / 'docs_manifest.json' + docs_file = script_dir / 'docs.html' + ai_ref_file = script_dir / 'AI_REFERENCE.md' + + errors = [] + warnings = [] + + # Check if all required files exist + if not index_file.exists(): + errors.append(f"ERROR: index.html not found at {index_file}") + return errors, warnings + + if not manifest_file.exists(): + errors.append(f"ERROR: Documentation manifest not found at {manifest_file}. Run generate_docs.py first.") + return errors, warnings + + if not docs_file.exists(): + errors.append(f"ERROR: User documentation not found at {docs_file}. Run generate_docs.py first.") + + if not ai_ref_file.exists(): + errors.append(f"ERROR: AI reference not found at {ai_ref_file}. Run generate_docs.py first.") + + # Extract current definitions from index.html + print("Extracting definitions from index.html...") + import subprocess + result = subprocess.run(['python3', 'extract_definitions.py'], cwd=script_dir, capture_output=True, text=True) + if result.returncode != 0: + errors.append(f"ERROR: Failed to extract definitions: {result.stderr}") + return errors, warnings + + # Load extracted definitions + extracted_file = script_dir / 'extracted_definitions.json' + if not extracted_file.exists(): + errors.append("ERROR: Could not find extracted definitions") + return errors, warnings + + with open(extracted_file, 'r') as f: + current_defs = json.load(f) + + # Load documentation manifest + with open(manifest_file, 'r') as f: + manifest = json.load(f) + + # Check if manifest is stale (older than 24 hours) + if 'generated_at' in manifest: + generated_time = datetime.fromisoformat(manifest['generated_at']) + age_hours = (datetime.now() - generated_time).total_seconds() / 3600 + if age_hours > 24: + warnings.append(f"WARNING: Documentation was generated {age_hours:.1f} hours ago. Consider regenerating.") + + # Extract all current queries and transitions + current_queries = set() + current_transitions = set() + + for cat_key, category in current_defs.get('queries', {}).items(): + for query_key in category.get('queries', {}).keys(): + # Skip invalid entries + if query_key not in ['dependsOn', 'offset', 'limit']: + current_queries.add(query_key) + + for cat_key, category in current_defs.get('transitions', {}).items(): + for trans_key in category.get('transitions', {}).keys(): + # Skip invalid entries + if trans_key not in ['dependsOn']: + current_transitions.add(trans_key) + + documented_queries = set(manifest.get('queries', {}).keys()) + documented_transitions = set(manifest.get('transitions', {}).keys()) + + # Find undocumented items + undocumented_queries = current_queries - documented_queries + undocumented_transitions = current_transitions - documented_transitions + + # Find removed items (documented but no longer in code) + removed_queries = documented_queries - current_queries + removed_transitions = documented_transitions - current_transitions + + # Report findings + if undocumented_queries: + errors.append(f"ERROR: {len(undocumented_queries)} queries are not documented:") + for q in sorted(undocumented_queries): + errors.append(f" - {q}") + + if undocumented_transitions: + errors.append(f"ERROR: {len(undocumented_transitions)} state transitions are not documented:") + for t in sorted(undocumented_transitions): + errors.append(f" - {t}") + + if removed_queries: + warnings.append(f"WARNING: {len(removed_queries)} queries are documented but no longer exist:") + for q in sorted(removed_queries): + warnings.append(f" - {q}") + + if removed_transitions: + warnings.append(f"WARNING: {len(removed_transitions)} transitions are documented but no longer exist:") + for t in sorted(removed_transitions): + warnings.append(f" - {t}") + + # Check file timestamps + index_mtime = os.path.getmtime(index_file) + + if docs_file.exists(): + docs_mtime = os.path.getmtime(docs_file) + if index_mtime > docs_mtime: + warnings.append("WARNING: index.html has been modified after docs.html was generated") + + if ai_ref_file.exists(): + ai_mtime = os.path.getmtime(ai_ref_file) + if index_mtime > ai_mtime: + warnings.append("WARNING: index.html has been modified after AI_REFERENCE.md was generated") + + return errors, warnings + +def main(): + """Main function""" + + errors, warnings = check_documentation_completeness() + + # Write report + report_lines = [] + report_lines.append("=" * 80) + report_lines.append("Documentation Completeness Check") + report_lines.append("=" * 80) + report_lines.append(f"Timestamp: {datetime.now().isoformat()}\n") + + if not errors and not warnings: + report_lines.append("✅ All documentation is up to date!") + else: + if warnings: + report_lines.append(f"⚠️ {len(warnings)} warnings found:\n") + for warning in warnings: + report_lines.append(warning) + report_lines.append("") + + if errors: + report_lines.append(f"❌ {len(errors)} errors found:\n") + for error in errors: + report_lines.append(error) + report_lines.append("") + + report_lines.append("=" * 80) + + if errors: + report_lines.append("\nTo fix these errors, run: python3 generate_docs.py") + + # Print report + report = '\n'.join(report_lines) + print(report) + + # Save report + with open('documentation-check-report.txt', 'w') as f: + f.write(report) + + # Exit with error if there are any errors + return 1 if errors else 0 + +if __name__ == '__main__': + sys.exit(main()) \ No newline at end of file diff --git a/packages/wasm-sdk/docs.html b/packages/wasm-sdk/docs.html new file mode 100644 index 00000000000..40e1b20d0af --- /dev/null +++ b/packages/wasm-sdk/docs.html @@ -0,0 +1,3031 @@ + + + + + + Dash Platform WASM JS SDK Documentation + + + + + + + +
+
+
Loading WASM module...
+
+
+
+
+
0%
+
+
+
+ + + + + +
+ + +

Dash Platform WASM JS SDK Documentation

+ +
+

Overview

+

The Dash Platform WASM JS SDK provides a WebAssembly-based interface for interacting with the Dash Platform from JavaScript and TypeScript applications. + This documentation covers all available queries and state transitions.

+ +

Key Concepts

+ + +

Note: All examples below can be run directly in your browser using the testnet. Click the "Run" button to execute any example.

+ +
+ Test Identity: All examples use the testnet identity 5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk +
This is a known identity with activity on testnet that you can use for testing. +
+
+ +

Queries

+ +
+

Identity Queries

+ +
+

Get Identity

+

Fetch an identity by its identifier

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.identity_fetch(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk');
+ +
+
+
+ +
+

Get Identity Keys

+

Retrieve keys associated with an identity

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ Key Request Type + select + (optional) +
Options: All Keys (AllKeys {}) - Get all keys for the identity, Specific Keys (SpecificKeys with key_ids) - Get specific keys by ID [🚧 Work in Progress], Search Keys (SearchKey with purpose_map) - Search by purpose and security level [🚧 Work in Progress]
+
+ Specific Key IDs (required for 'specific' type) + array + (optional) +
Example: 0,1,2
+
+ Search Purpose Map JSON (required for 'search' type) + text + (optional) +
Example: {"0": {"0": "current"}, "1": {"0": "all"}}
+
+ +
+
Example
+
return await window.wasmFunctions.get_identity_keys(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk', 'all');
+ +
+
Example 2 - Get Specific Keys
+
return await window.wasmFunctions.get_identity_keys(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk', 'specific', [0, 1, 2]);
+ +
+
+
+
+
+ +
+

Get Identities Contract Keys

+

Get keys for multiple identities related to a specific contract

+ +
+
Parameters:
+ +
+ Identity IDs + array + (required) +
+
+ Contract ID + text + (required) +
+
+ Document Type (optional) + text + (optional) +
+
+ Key Request Type + select + (optional) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_identities_contract_keys(sdk, ['5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk'], 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', 'domain', 'all');
+ +
+
+
+ +
+

Get Identity Nonce

+

Get the current nonce for an identity

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_identity_nonce(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk');
+ +
+
+
+ +
+

Get Identity Contract Nonce

+

Get the nonce for an identity in relation to a specific contract

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ Contract ID + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_identity_contract_nonce(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk', 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec');
+ +
+
+
+ +
+

Get Identity Balance

+

Get the credit balance of an identity

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_identity_balance(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk');
+ +
+
+
+ +
+

Get Identities Balances

+

Get balances for multiple identities

+ +
+
Parameters:
+ +
+ Identity IDs + array + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_identities_balances(sdk, ['5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk']);
+ +
+
+
+ +
+

Get Identity Balance and Revision

+

Get both balance and revision number for an identity

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_identity_balance_and_revision(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk');
+ +
+
+
+ +
+

Get Identity by Unique Public Key Hash

+

Find an identity by its unique public key hash

+ +
+
Parameters:
+ +
+ Public Key Hash + text + (required) +
Example: b7e904ce25ed97594e72f7af0e66f298031c1754
+
+ +
+
Example
+
return await window.wasmFunctions.get_identity_by_public_key_hash(sdk, 'b7e904ce25ed97594e72f7af0e66f298031c1754');
+ +
+
+
+ +
+

Get Identity by Non-Unique Public Key Hash

+

Find identities by non-unique public key hash

+ +
+
Parameters:
+ +
+ Public Key Hash + text + (required) +
Example: 518038dc858461bcee90478fd994bba8057b7531
+
+ +
+
Example
+
return await window.wasmFunctions.get_identity_by_non_unique_public_key_hash(sdk, '518038dc858461bcee90478fd994bba8057b7531');
+ +
+
+
+ +
+

Get Identity Token Balances

+

Get token balances for an identity

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ Token IDs + array + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_identity_token_balances(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk', ['Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv']);
+ +
+
+
+ +
+

Get Identities Token Balances

+

Get token balance for multiple identities

+ +
+
Parameters:
+ +
+ Identity IDs + array + (required) +
+
+ Token ID + text + (required) +
Example: Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv
+
+ +
+
Example
+
return await window.wasmFunctions.get_identities_token_balances(sdk, ['5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk'], 'Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv');
+ +
+
+
+ +
+

Get Identity Token Info

+

Get token information for an identity's tokens

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ Token IDs (optional) + array + (optional) +
Example: ["Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv"]
+
+ +
+
Example
+
return await window.wasmFunctions.get_identity_token_infos(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk', ['Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv']);
+ +
+
+
+ +
+

Get Identities Token Info

+

Get token information for multiple identities with a specific token

+ +
+
Parameters:
+ +
+ Identity IDs + array + (required) +
+
+ Token ID + text + (required) +
Example: Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv
+
+ +
+
Example
+
return await window.wasmFunctions.get_identities_token_infos(sdk, ['5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk'], 'Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv');
+ +
+
+
+
+
+

Data Contract Queries

+ +
+

Get Data Contract

+

Fetch a data contract by its identifier

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
Example: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec
+
+ +
+
Example
+
return await window.wasmFunctions.data_contract_fetch(sdk, 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec');
+ +
+
+
+ +
+

Get Data Contract History

+

Get the version history of a data contract

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
Example: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec
+
+ Limit + number + (optional) +
Default: 100 (maximum items returned if not specified)
+
+ Offset + number + (optional) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_data_contract_history(sdk, 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', 10, 0);
+ 🚧 Work in Progress +
+
+
+ +
+

Get Data Contracts

+

Fetch multiple data contracts by their identifiers

+ +
+
Parameters:
+ +
+ Data Contract IDs + array + (required) +
Example: ["GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec", "ALybvzfcCwMs7sinDwmtumw17NneuW7RgFtFHgjKmF3A"]
+
+ +
+
Example
+
return await window.wasmFunctions.get_data_contracts(sdk, ['GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', 'ALybvzfcCwMs7sinDwmtumw17NneuW7RgFtFHgjKmF3A']);
+ +
+
+
+
+
+

Document Queries

+ +
+

Get Documents

+

Query documents from a data contract

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
Example: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec
+
+ Document Type + text + (required) +
Example: domain
+
+ Where Clause (JSON) + text + (optional) +
Example: [["normalizedParentDomainName", "==", "dash"], ["normalizedLabel", "==", "therea1s11mshaddy5"]]
+
+ Order By (JSON) + text + (optional) +
Example: [["$createdAt", "desc"]]
+
+ Limit + number + (optional) +
Default: 100 (maximum items returned if not specified)
+
+ +
+
Example
+
return await window.wasmFunctions.get_documents(sdk, 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', 'domain', JSON.stringify([["normalizedParentDomainName", "==", "dash"]]), JSON.stringify([["normalizedLabel", "asc"]]), 10);
+ +
+
+
+ +
+

Get Document

+

Fetch a specific document by ID

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
Example: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec
+
+ Document Type + text + (required) +
Example: domain
+
+ Document ID + text + (required) +
Example: 7NYmEKQsYtniQRUmxwdPGeVcirMoPh5ZPyAKz8BWFy3r
+
+ +
+
Example
+
return await window.wasmFunctions.get_document(sdk, 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', 'domain', '7NYmEKQsYtniQRUmxwdPGeVcirMoPh5ZPyAKz8BWFy3r');
+ +
+
+
+
+
+

DPNS Queries

+ +
+

Get DPNS Usernames

+

Get DPNS usernames for an identity

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_dpns_usernames(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk');
+ +
+
+
+ +
+

DPNS Check Availability

+

Check if a DPNS username is available

+ +
+
Parameters:
+ +
+ Label (Username) + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.dpns_is_name_available(sdk, 'alice');
+ +
+
+
+ +
+

DPNS Resolve Name

+

Resolve a DPNS name to an identity ID

+ +
+
Parameters:
+ +
+ Name + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.dpns_resolve_name(sdk, 'alice');
+ +
+
+
+
+
+

Voting & Contested Resources

+ +
+

Get Contested Resources

+

Get list of contested resources

+ +
+
Parameters:
+ +
+ Result Type + select + (required) +
+
+ Document Type + text + (required) +
+
+ Index Name + text + (required) +
+
+ Count + number + (optional) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_contested_resources(sdk, 'documents', 'domain', 'parentNameAndLabel', 100);
+ +
+
+
+ +
+

Get Contested Resource Vote State

+

Get the current vote state for a contested resource

+ +
+
Parameters:
+ +
+ Contract ID + text + (required) +
+
+ Document Type + text + (required) +
+
+ Index Name + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_contested_resource_vote_state(sdk, 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', 'domain', 'parentNameAndLabel');
+ +
+
+
+ +
+

Get Contested Resource Voters for Identity

+

Get voters who voted for a specific identity in a contested resource

+ +
+
Parameters:
+ +
+ Contract ID + text + (required) +
+
+ Document Type + text + (required) +
+
+ Index Name + text + (required) +
+
+ Contestant Identity ID + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_contested_resource_voters_for_identity(sdk, 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', 'domain', 'parentNameAndLabel', '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk');
+ 🚧 Work in Progress +
+
+
+ +
+

Get Contested Resource Identity Votes

+

Get all votes cast by a specific identity

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_contested_resource_identity_votes(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk');
+ +
+
+
+ +
+

Get Vote Polls by End Date

+

Get vote polls within a time range

+ +
+
Parameters:
+ +
+ Start Time (ms) + number + (required) +
+
+ End Time (ms) + number + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_vote_polls_by_end_date(sdk, Date.now() - 86400000, Date.now());
+ +
+
+
+
+
+

Protocol & Version

+ +
+

Get Protocol Version Upgrade State

+

Get the current state of protocol version upgrades

+ +
+
Parameters:
+

No parameters required

+
+ +
+
Example
+
return await window.wasmFunctions.get_protocol_version_upgrade_state(sdk);
+ +
+
+
+ +
+

Get Protocol Version Upgrade Vote Status

+

Get voting status for protocol version upgrades

+ +
+
Parameters:
+ +
+ Start ProTx Hash + text + (required) +
Example: 143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113
+
+ Count + number + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_protocol_version_upgrade_vote_status(sdk, '143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113', 100);
+ +
+
+
+
+
+

Epoch & Block

+ +
+

Get Epochs Info

+

Get information about epochs

+ +
+
Parameters:
+ +
+ Start Epoch + number + (required) +
+
+ Count + number + (required) +
+
+ Ascending Order + checkbox + (optional) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_epochs_info(sdk, 1000, 100, true);
+ +
+
+
+ +
+

Get Current Epoch

+

Get information about the current epoch

+ +
+
Parameters:
+

No parameters required

+
+ +
+
Example
+
return await window.wasmFunctions.get_current_epoch(sdk);
+ +
+
+
+ +
+

Get Finalized Epoch Info

+

Get information about finalized epochs

+ +
+
Parameters:
+ +
+ Start Epoch + number + (required) +
+
+ Count + number + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_finalized_epoch_infos(sdk, 8635, 100);
+ +
+
+
+ +
+

Get Evonodes Proposed Epoch Blocks by IDs

+

Get proposed blocks by evonode IDs

+ +
+
Parameters:
+ +
+ ProTx Hashes + array + (required) +
Example: ["143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113"]
+
+ +
+
Example
+
return await window.wasmFunctions.get_evonodes_proposed_epoch_blocks_by_ids(sdk, ['143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113']);
+ +
+
+
+ +
+

Get Evonodes Proposed Epoch Blocks by Range

+

Get proposed blocks by range

+ +
+
Parameters:
+ +
+ Start ProTx Hash + text + (required) +
Example: 143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113
+
+ Count + number + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_evonodes_proposed_epoch_blocks_by_range(sdk, '143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113', 100);
+ +
+
+
+
+
+

Token Queries

+ +
+

Get Token Statuses

+

Get token statuses

+ +
+
Parameters:
+ +
+ Token IDs + array + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_token_statuses(sdk, ['Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv', 'H7FRpZJqZK933r9CzZMsCuf1BM34NT5P2wSJyjDkprqy']);
+ +
+
+
+ +
+

Get Token Direct Purchase Prices

+

Get direct purchase prices for tokens

+ +
+
Parameters:
+ +
+ Token IDs + array + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_token_direct_purchase_prices(sdk, ['H7FRpZJqZK933r9CzZMsCuf1BM34NT5P2wSJyjDkprqy']);
+ +
+
+
+ +
+

Get Token Contract Info

+

Get information about a token contract

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
Example: EETVvWgohFDKtbB3ejEzBcDRMNYkc9TtgXY6y8hzP3Ta
+
+ +
+
Example
+
return await window.wasmFunctions.get_token_contract_info(sdk, 'EETVvWgohFDKtbB3ejEzBcDRMNYkc9TtgXY6y8hzP3Ta');
+ +
+
+
+ +
+

Get Token Perpetual Distribution Last Claim

+

Get last claim information for perpetual distribution

+ +
+
Parameters:
+ +
+ Identity ID + text + (required) +
+
+ Token ID + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_token_perpetual_distribution_last_claim(sdk, '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk', 'EETVvWgohFDKtbB3ejEzBcDRMNYkc9TtgXY6y8hzP3Ta');
+ 🚧 Work in Progress +
+
+
+ +
+

Get Token Total Supply

+

Get total supply of a token

+ +
+
Parameters:
+ +
+ Token ID + text + (required) +
Example: Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv
+
+ +
+
Example
+
return await window.wasmFunctions.get_token_total_supply(sdk, 'Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv');
+ +
+
+
+
+
+

Group Queries

+ +
+

Get Group Info

+

Get information about a group

+ +
+
Parameters:
+ +
+ Contract ID + text + (required) +
+
+ Group Contract Position + number + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_group_info(sdk, '49PJEnNx7ReCitzkLdkDNr4s6RScGsnNexcdSZJ1ph5N', 0);
+ +
+
+
+ +
+

Get Group Infos

+

Get information about multiple groups

+ +
+
Parameters:
+ +
+ Contract ID + text + (required) +
+
+ Start at Position + number + (optional) +
+
+ Include Start Position + checkbox + (optional) +
+
+ Count + number + (optional) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_group_infos(sdk, '49PJEnNx7ReCitzkLdkDNr4s6RScGsnNexcdSZJ1ph5N', null, 100);
+ +
+
+
+ +
+

Get Group Actions

+

Get actions for a group

+ +
+
Parameters:
+ +
+ Contract ID + text + (required) +
+
+ Group Contract Position + number + (required) +
+
+ Status + select + (required) +
Options: Active, Closed
+
+ Start Action ID + text + (optional) +
+
+ Include Start Action + checkbox + (optional) +
+
+ Count + number + (optional) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_group_actions(sdk, '49PJEnNx7ReCitzkLdkDNr4s6RScGsnNexcdSZJ1ph5N', 0, 'ACTIVE', null, 100);
+ +
+
+
+ +
+

Get Group Action Signers

+

Get signers for a group action

+ +
+
Parameters:
+ +
+ Contract ID + text + (required) +
+
+ Group Contract Position + number + (required) +
+
+ Status + select + (required) +
Options: Active, Closed
+
+ Action ID + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_group_action_signers(sdk, '49PJEnNx7ReCitzkLdkDNr4s6RScGsnNexcdSZJ1ph5N', 0, 'ACTIVE', '6XJzL6Qb8Zhwxt4HFwh8NAn7q1u4dwdoUf8EmgzDudFZ');
+ +
+
+
+
+
+

System & Utility

+ +
+

Get Status

+

Get system status

+ +
+
Parameters:
+

No parameters required

+
+ +
+
Example
+
return await window.wasmFunctions.get_status(sdk);
+ +
+
+
+ +
+

Get Current Quorums Info

+

Get information about current quorums

+ +
+
Parameters:
+

No parameters required

+
+ +
+
Example
+
return await window.wasmFunctions.get_current_quorums_info(sdk);
+ +
+
+
+ +
+

Get Prefunded Specialized Balance

+

Get prefunded specialized balance

+ +
+
Parameters:
+ +
+ Specialized Balance ID + text + (required) +
Example: AzaU7zqCT7X1kxh8yWxkT9PxAgNqWDu4Gz13emwcRyAT
+
+ +
+
Example
+
return await window.wasmFunctions.get_prefunded_specialized_balance(sdk, 'AzaU7zqCT7X1kxh8yWxkT9PxAgNqWDu4Gz13emwcRyAT');
+ +
+
+
+ +
+

Get Total Credits in Platform

+

Get total credits in the platform

+ +
+
Parameters:
+

No parameters required

+
+ +
+
Example
+
return await window.wasmFunctions.get_total_credits_in_platform(sdk);
+ +
+
+
+ +
+

Get Path Elements

+

Access any data in the Dash Platform state tree. This low-level query allows direct access to GroveDB storage by specifying a path through the tree structure and keys to retrieve at that path. Common paths include: Identities (32), Tokens (96), DataContractDocuments (64), Balances (16), Votes (80), and more.

+ +
+
Parameters:
+ +
+ Path + array + (required) +
+
+ Keys + array + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.get_path_elements(sdk, ['96'], ['5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk']);
+ 🚧 Work in Progress +
+
Common Path Values:
+ + + + + + + + + + + + + + + + +
Path ValueDescription
64Data Contract Documents
32Identities
24Unique Public Key Hashes to Identities
8Non-Unique Public Key Hashes to Identities
16Tokens
48Pools
40Prefunded Specialized Balances
72Spent Asset Lock Transactions
80Withdrawal Transactions
88Group Actions
96Balances
104Misc
112Votes
120Versions
+
Example Paths:
+
    +
  • [32, identity_id] - Access identity data
  • +
  • [96, identity_id] - Access identity balance
  • +
  • [16, contract_id, token_id] - Access token info
  • +
  • [64, contract_id, 1, document_type] - Access documents by type
  • +
  • [88, contract_id, group_position] - Access group actions
  • +
  • [112] - Access votes tree
  • +
+
+
+
+
+ +
+

Wait for State Transition Result

+

Internal query to wait for and retrieve the result of a previously submitted state transition

+ +
+
Parameters:
+ +
+ State Transition Hash + text + (required) +
+
+ +
+
Example
+
return await window.wasmFunctions.wait_for_state_transition_result(sdk, '0000000000000000000000000000000000000000000000000000000000000000');
+

This is an internal query used to wait for and retrieve the result of a previously submitted state transition. It requires a valid state transition hash from a prior operation.

+
+
+
+

State Transitions

+
+

Identity Transitions

+ +
+

Identity Create

+

Create a new identity with initial credits

+ +
+
Parameters:
+ +
+ Public Keys + keyArray + (required) +
+
+ Asset Lock Proof + assetLockProof + (required) +
+
+
+ +
+

Identity Top Up

+

Add credits to an existing identity

+ +
+
Parameters:
+ +
+ Asset Lock Proof + assetLockProof + (required) +
+
+
+ +
+

Identity Update

+

Update identity keys (add or disable)

+ +
+
Parameters:
+ +
+ Keys to Add (JSON array) + textarea + (optional) +
Example: [{"keyType":"ECDSA_HASH160","purpose":"AUTHENTICATION","data":"base64_key_data"}]
+
+ Key IDs to Disable (comma-separated) + text + (optional) +
Example: 2,3,5
+
+
+ +
+

Identity Credit Transfer

+

Transfer credits between identities

+ +
+
Parameters:
+ +
+ Recipient Identity ID + text + (required) +
+
+ Amount (credits) + number + (required) +
+
+
+ +
+

Identity Credit Withdrawal

+

Withdraw credits from identity to Dash address

+ +
+
Parameters:
+ +
+ Dash Address + text + (required) +
+
+ Amount (credits) + number + (required) +
+
+ Core Fee Per Byte (optional) + number + (optional) +
+
+
+
+
+

Data Contract Transitions

+ +
+

Data Contract Create

+

Create a new data contract

+ +
+
Parameters:
+ +
+ Can Be Deleted + checkbox + (optional) +
+
+ Read Only + checkbox + (optional) +
+
+ Keeps History + checkbox + (optional) +
+
+ Documents Keep History (Default) + checkbox + (optional) +
+
+ Documents Mutable (Default) + checkbox + (optional) +
+
+ Documents Can Be Deleted (Default) + checkbox + (optional) +
+
+ Requires Identity Encryption Key (optional) + text + (optional) +
+
+ Requires Identity Decryption Key (optional) + text + (optional) +
+
+ Document Schemas JSON + json + (required) +
Example: { + "note": { + "type": "object", + "properties": { + "message": { + "type": "string", + "maxLength": 100, + "position": 0 + } + }, + "required": ["message"], + "additionalProperties": false + } +}
+
+ Groups (optional) + json + (optional) +
Example: {}
+
+ Tokens (optional) + json + (optional) +
Example: {}
+
+ Keywords (comma separated, optional) + text + (optional) +
+
+ Description (optional) + text + (optional) +
+
+
+ +
+

Data Contract Update

+

Add document types, groups, or tokens to an existing data contract

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ New Document Schemas to Add (optional) + json + (optional) +
Example: { + "newType": { + "type": "object", + "properties": { + "field": { + "type": "string", + "maxLength": 100, + "position": 0 + } + }, + "required": ["field"], + "additionalProperties": false + } +}
+
+ New Groups to Add (optional) + json + (optional) +
Example: {}
+
+ New Tokens to Add (optional) + json + (optional) +
Example: {}
+
+
+
+
+

Document Transitions

+ +
+

Document Create

+

Create a new document

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Document Type + text + (required) +
+
+ Fetch Schema + button + (optional) +
+
+ Document Fields + dynamic + (optional) +
+
+
+ +
+

Document Replace

+

Replace an existing document

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Document Type + text + (required) +
+
+ Document ID + text + (required) +
+
+ Load Document + button + (optional) +
+
+ Document Fields + dynamic + (optional) +
+
+
+ +
+

Document Delete

+

Delete an existing document

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Document Type + text + (required) +
+
+ Document ID + text + (required) +
+
+
+ +
+

Document Transfer

+

Transfer document ownership

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Document Type + text + (required) +
+
+ Document ID + text + (required) +
+
+ Recipient Identity ID + text + (required) +
+
+
+ +
+

Document Purchase

+

Purchase a document

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Document Type + text + (required) +
+
+ Document ID + text + (required) +
+
+ Price (credits) + number + (required) +
+
+
+ +
+

Document Set Price

+

Set or update document price

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Document Type + text + (required) +
+
+ Document ID + text + (required) +
+
+ Price (credits, 0 to remove) + number + (required) +
+
+
+ +
+

DPNS Register Name

+

Register a new DPNS username

+ +
+
Parameters:
+ +
+ Username + text + (required) +
Example: Enter username (e.g., alice)
+
+
+
+
+

Token Transitions

+ +
+

Token Burn

+

Burn tokens

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Token Contract Position + number + (required) +
+
+ Amount to Burn + text + (required) +
+
+ Key ID (for signing) + number + (required) +
+
+ Public Note + text + (optional) +
+
+
+ +
+

Token Mint

+

Mint new tokens

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Token Contract Position + number + (required) +
+
+ Amount to Mint + text + (required) +
+
+ Key ID (for signing) + number + (required) +
+
+ Issue To Identity ID + text + (optional) +
+
+ Public Note + text + (optional) +
+
+
+ +
+

Token Transfer

+

Transfer tokens to another identity

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Token Contract Position + text + (required) +
+
+ Amount to Transfer + number + (required) +
+
+ Recipient Identity ID + text + (required) +
+
+
+ +
+

Token Freeze

+

Freeze tokens for an identity

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Token Contract Position + text + (required) +
+
+ Identity ID to Freeze + text + (required) +
+
+
+ +
+

Token Unfreeze

+

Unfreeze tokens for an identity

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Token Contract Position + text + (required) +
+
+ Identity ID to Unfreeze + text + (required) +
+
+
+ +
+

Token Destroy Frozen Funds

+

Destroy frozen tokens

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
+
+ Token Contract Position + text + (required) +
+
+ Identity ID + text + (required) +
+
+
+
+
+

Voting Transitions

+ +
+

DPNS Username

+

Cast a vote for a contested DPNS username

+ +
+
Parameters:
+ +
+ Contested Username + text + (required) +
Example: Enter the contested username (e.g., 'myusername')
+
+ Vote Choice + select + (required) +
Options: Abstain, Lock (Give to no one), Vote for Identity
+
+ Target Identity ID (if voting for identity) + text + (optional) +
Example: Identity ID to vote for
+
+
+ +
+

Contested Resource

+

Cast a vote for contested resources as a masternode

+ +
+
Parameters:
+ +
+ Data Contract ID + text + (required) +
Example: Contract ID containing the contested resource
+
+ Get Contested Resources + button + (optional) +
+
+ Contested Resources + dynamic + (optional) +
+
+ Vote Choice + select + (required) +
Options: Abstain, Lock (Give to no one), Vote for Identity
+
+ Target Identity ID (if voting for identity) + text + (optional) +
Example: Identity ID to vote for
+
+
+
+ ↑ Top +
+ + + + diff --git a/packages/wasm-sdk/docs_manifest.json b/packages/wasm-sdk/docs_manifest.json new file mode 100644 index 00000000000..14232e07a48 --- /dev/null +++ b/packages/wasm-sdk/docs_manifest.json @@ -0,0 +1,291 @@ +{ + "generated_at": "2025-07-14T10:43:09.496444", + "queries": { + "getIdentity": { + "category": "identity", + "documented": true + }, + "getIdentityKeys": { + "category": "identity", + "documented": true + }, + "getIdentitiesContractKeys": { + "category": "identity", + "documented": true + }, + "getIdentityNonce": { + "category": "identity", + "documented": true + }, + "getIdentityContractNonce": { + "category": "identity", + "documented": true + }, + "getIdentityBalance": { + "category": "identity", + "documented": true + }, + "getIdentitiesBalances": { + "category": "identity", + "documented": true + }, + "getIdentityBalanceAndRevision": { + "category": "identity", + "documented": true + }, + "getIdentityByPublicKeyHash": { + "category": "identity", + "documented": true + }, + "getIdentityByNonUniquePublicKeyHash": { + "category": "identity", + "documented": true + }, + "getIdentityTokenBalances": { + "category": "identity", + "documented": true + }, + "getIdentitiesTokenBalances": { + "category": "identity", + "documented": true + }, + "getIdentityTokenInfos": { + "category": "identity", + "documented": true + }, + "getIdentitiesTokenInfos": { + "category": "identity", + "documented": true + }, + "getDataContract": { + "category": "dataContract", + "documented": true + }, + "getDataContractHistory": { + "category": "dataContract", + "documented": true + }, + "getDataContracts": { + "category": "dataContract", + "documented": true + }, + "getDocuments": { + "category": "document", + "documented": true + }, + "getDocument": { + "category": "document", + "documented": true + }, + "getDpnsUsername": { + "category": "dpns", + "documented": true + }, + "dpnsCheckAvailability": { + "category": "dpns", + "documented": true + }, + "dpnsResolve": { + "category": "dpns", + "documented": true + }, + "getContestedResources": { + "category": "voting", + "documented": true + }, + "getContestedResourceVoteState": { + "category": "voting", + "documented": true + }, + "getContestedResourceVotersForIdentity": { + "category": "voting", + "documented": true + }, + "getContestedResourceIdentityVotes": { + "category": "voting", + "documented": true + }, + "getVotePollsByEndDate": { + "category": "voting", + "documented": true + }, + "getProtocolVersionUpgradeState": { + "category": "protocol", + "documented": true + }, + "getProtocolVersionUpgradeVoteStatus": { + "category": "protocol", + "documented": true + }, + "getEpochsInfo": { + "category": "epoch", + "documented": true + }, + "getCurrentEpoch": { + "category": "epoch", + "documented": true + }, + "getFinalizedEpochInfos": { + "category": "epoch", + "documented": true + }, + "getEvonodesProposedEpochBlocksByIds": { + "category": "epoch", + "documented": true + }, + "getEvonodesProposedEpochBlocksByRange": { + "category": "epoch", + "documented": true + }, + "getTokenStatuses": { + "category": "token", + "documented": true + }, + "getTokenDirectPurchasePrices": { + "category": "token", + "documented": true + }, + "getTokenContractInfo": { + "category": "token", + "documented": true + }, + "getTokenPerpetualDistributionLastClaim": { + "category": "token", + "documented": true + }, + "getTokenTotalSupply": { + "category": "token", + "documented": true + }, + "getGroupInfo": { + "category": "group", + "documented": true + }, + "getGroupInfos": { + "category": "group", + "documented": true + }, + "getGroupActions": { + "category": "group", + "documented": true + }, + "getGroupActionSigners": { + "category": "group", + "documented": true + }, + "getStatus": { + "category": "system", + "documented": true + }, + "getCurrentQuorumsInfo": { + "category": "system", + "documented": true + }, + "getPrefundedSpecializedBalance": { + "category": "system", + "documented": true + }, + "getTotalCreditsInPlatform": { + "category": "system", + "documented": true + }, + "getPathElements": { + "category": "system", + "documented": true + }, + "waitForStateTransitionResult": { + "category": "system", + "documented": true + } + }, + "transitions": { + "identityCreate": { + "category": "identity", + "documented": true + }, + "identityTopUp": { + "category": "identity", + "documented": true + }, + "identityUpdate": { + "category": "identity", + "documented": true + }, + "identityCreditTransfer": { + "category": "identity", + "documented": true + }, + "identityCreditWithdrawal": { + "category": "identity", + "documented": true + }, + "dataContractCreate": { + "category": "dataContract", + "documented": true + }, + "dataContractUpdate": { + "category": "dataContract", + "documented": true + }, + "documentCreate": { + "category": "document", + "documented": true + }, + "documentReplace": { + "category": "document", + "documented": true + }, + "documentDelete": { + "category": "document", + "documented": true + }, + "documentTransfer": { + "category": "document", + "documented": true + }, + "documentPurchase": { + "category": "document", + "documented": true + }, + "documentSetPrice": { + "category": "document", + "documented": true + }, + "dpnsRegister": { + "category": "document", + "documented": true + }, + "tokenBurn": { + "category": "token", + "documented": true + }, + "tokenMint": { + "category": "token", + "documented": true + }, + "tokenTransfer": { + "category": "token", + "documented": true + }, + "tokenFreeze": { + "category": "token", + "documented": true + }, + "tokenUnfreeze": { + "category": "token", + "documented": true + }, + "tokenDestroyFrozen": { + "category": "token", + "documented": true + }, + "dpnsUsername": { + "category": "voting", + "documented": true + }, + "masternodeVote": { + "category": "voting", + "documented": true + } + } +} \ No newline at end of file diff --git a/packages/wasm-sdk/extract_definitions.py b/packages/wasm-sdk/extract_definitions.py new file mode 100644 index 00000000000..1afd42374ee --- /dev/null +++ b/packages/wasm-sdk/extract_definitions.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python3 +""" +Extract query and state transition definitions from index.html +""" + +import json +import re +from pathlib import Path + +def manual_extract_definitions(html_file): + """Manually extract definitions using targeted patterns""" + + with open(html_file, 'r', encoding='utf-8') as f: + content = f.read() + + # Extract the complete queryDefinitions block + query_start = content.find('const queryDefinitions = {') + if query_start == -1: + return {}, {} + + # Find the end by counting braces + brace_count = 0 + pos = query_start + len('const queryDefinitions = ') + query_end = pos + + for i, char in enumerate(content[pos:], pos): + if char == '{': + brace_count += 1 + elif char == '}': + brace_count -= 1 + if brace_count == 0: + query_end = i + 1 + break + + query_block = content[pos:query_end] + + # Extract state transition definitions + trans_start = content.find('const stateTransitionDefinitions = {') + if trans_start == -1: + return {}, {} + + brace_count = 0 + pos = trans_start + len('const stateTransitionDefinitions = ') + trans_end = pos + + for i, char in enumerate(content[pos:], pos): + if char == '{': + brace_count += 1 + elif char == '}': + brace_count -= 1 + if brace_count == 0: + trans_end = i + 1 + break + + trans_block = content[pos:trans_end] + + # Parse definitions + query_defs = parse_definition_block(query_block, 'queries') + trans_defs = parse_definition_block(trans_block, 'transitions') + + return query_defs, trans_defs + +def parse_definition_block(block, item_type): + """Parse a definition block into structured data""" + definitions = {} + + # First, find all category blocks with the pattern: categoryName: { label: "...", queries/transitions: { ... } } + # We need to match the full category structure, not just anything with a label + cat_pattern = r'(\w+):\s*\{\s*label:\s*"([^"]+)"[^}]*' + item_type + r':\s*\{' + + for match in re.finditer(cat_pattern, block): + cat_key = match.group(1) + cat_label = match.group(2) + + # Skip if this looks like it's inside another structure + # Check if the match is at the top level by ensuring no unclosed braces before it + prefix = block[:match.start()] + if prefix.count('{') - prefix.count('}') > 0: + continue + + # Find this category's content + cat_start = match.start() + + # Find the full category block by counting braces + brace_count = 0 + cat_end = cat_start + in_category = False + + for i, char in enumerate(block[cat_start:], cat_start): + if char == '{': + brace_count += 1 + in_category = True + elif char == '}': + brace_count -= 1 + if in_category and brace_count == 0: + cat_end = i + 1 + break + + cat_block = block[cat_start:cat_end] + + # Now extract just the queries/transitions section + items_pattern = rf'{item_type}:\s*\{{' + items_match = re.search(items_pattern, cat_block) + + if items_match: + items_start = items_match.end() + + # Find the end of the items section by counting braces + brace_count = 1 + items_end = items_start + + for i, char in enumerate(cat_block[items_start:], items_start): + if char == '{': + brace_count += 1 + elif char == '}': + brace_count -= 1 + if brace_count == 0: + items_end = i + break + + items_block = cat_block[items_start:items_end] + + # Extract individual items + definitions[cat_key] = { + 'label': cat_label, + item_type: parse_items(items_block) + } + + return definitions + +def parse_items(items_block): + """Parse individual query/transition items""" + items = {} + + # Find each item that has label and description structure + # This pattern ensures we only match actual query/transition definitions + item_pattern = r'(\w+):\s*\{\s*label:\s*"' + + matches = list(re.finditer(item_pattern, items_block)) + + for match in matches: + item_key = match.group(1) + item_start = match.start() + + # Find the full item block by counting braces + brace_count = 0 + item_end = item_start + in_item = False + + for j, char in enumerate(items_block[item_start:], item_start): + if char == '{': + brace_count += 1 + in_item = True + elif char == '}': + brace_count -= 1 + if in_item and brace_count == 0: + item_end = j + 1 + break + + item_content = items_block[item_start + match.end() - match.start():item_end - 1] + + # Extract item details + item_data = {} + + # Extract label + label_match = re.search(r'label:\s*"([^"]+)"', item_content) + if label_match: + item_data['label'] = label_match.group(1) + + # Extract description + desc_match = re.search(r'description:\s*"([^"]+)"', item_content) + if desc_match: + item_data['description'] = desc_match.group(1) + + # Extract inputs + inputs_match = re.search(r'inputs:\s*\[', item_content) + if inputs_match: + inputs_start = inputs_match.end() + + # Find the end of inputs array + bracket_count = 1 + inputs_end = inputs_start + + for j, char in enumerate(item_content[inputs_start:], inputs_start): + if char == '[': + bracket_count += 1 + elif char == ']': + bracket_count -= 1 + if bracket_count == 0: + inputs_end = j + break + + inputs_content = item_content[inputs_start:inputs_end] + item_data['inputs'] = parse_inputs(inputs_content) + else: + item_data['inputs'] = [] + + items[item_key] = item_data + + return items + +def parse_inputs(inputs_content): + """Parse input array""" + inputs = [] + + # Find each input object + obj_starts = [m.start() for m in re.finditer(r'\{', inputs_content)] + + for start in obj_starts: + # Find the matching closing brace + brace_count = 1 + end = start + 1 + + for i, char in enumerate(inputs_content[start + 1:], start + 1): + if char == '{': + brace_count += 1 + elif char == '}': + brace_count -= 1 + if brace_count == 0: + end = i + 1 + break + + obj_content = inputs_content[start:end] + + # Parse this input object + input_data = {} + + # Extract fields + fields = { + 'name': r'name:\s*"([^"]+)"', + 'type': r'type:\s*"([^"]+)"', + 'label': r'label:\s*"([^"]+)"', + 'placeholder': r'placeholder:\s*["\']([^"\']+)["\']', + } + + for field, pattern in fields.items(): + match = re.search(pattern, obj_content) + if match: + input_data[field] = match.group(1) + + # Extract required + req_match = re.search(r'required:\s*(true|false)', obj_content) + if req_match: + input_data['required'] = req_match.group(1) == 'true' + + # Extract options if present + options_match = re.search(r'options:\s*\[', obj_content) + if options_match: + options_start = options_match.end() + bracket_count = 1 + options_end = options_start + + for i, char in enumerate(obj_content[options_start:], options_start): + if char == '[': + bracket_count += 1 + elif char == ']': + bracket_count -= 1 + if bracket_count == 0: + options_end = i + break + + options_content = obj_content[options_start:options_end] + input_data['options'] = [] + + # Extract each option + opt_pattern = r'\{\s*value:\s*"([^"]+)"[^}]*label:\s*"([^"]+)"[^}]*\}' + for opt_match in re.finditer(opt_pattern, options_content): + input_data['options'].append({ + 'value': opt_match.group(1), + 'label': opt_match.group(2) + }) + + if input_data: + inputs.append(input_data) + + return inputs + +def main(): + index_file = Path(__file__).parent / 'index.html' + + if not index_file.exists(): + print(f"Error: {index_file} not found") + return 1 + + query_defs, trans_defs = manual_extract_definitions(index_file) + + # Save to JSON for inspection + output = { + 'queries': query_defs, + 'transitions': trans_defs + } + + with open('extracted_definitions.json', 'w') as f: + json.dump(output, f, indent=2) + + print(f"Extracted {sum(len(cat.get('queries', {})) for cat in query_defs.values())} queries") + print(f"Extracted {sum(len(cat.get('transitions', {})) for cat in trans_defs.values())} transitions") + + return 0 + +if __name__ == '__main__': + exit(main()) \ No newline at end of file diff --git a/packages/wasm-sdk/fixed_definitions.json b/packages/wasm-sdk/fixed_definitions.json new file mode 100644 index 00000000000..88cbec21441 --- /dev/null +++ b/packages/wasm-sdk/fixed_definitions.json @@ -0,0 +1,1658 @@ +{ + "queries": { + "identity": { + "label": "Identity Queries", + "queries": { + "getIdentity": { + "label": "Get Identity", + "description": "Fetch an identity by its identifier", + "inputs": [ + { + "name": "id", + "type": "text", + "label": "Identity ID", + "required": true + } + ] + }, + "getIdentityKeys": { + "label": "Get Identity Keys", + "description": "Retrieve keys associated with an identity", + "inputs": [ + { + "name": "identityId", + "type": "text", + "label": "Identity ID", + "required": true + }, + { + "name": "keyRequestType", + "type": "select", + "label": "Key Request Type", + "required": false, + "options": [ + { + "value": "all", + "label": "All Keys (AllKeys {}) - Get all keys for the identity" + }, + { + "value": "specific", + "label": "Specific Keys (SpecificKeys with key_ids) - Get specific keys by ID [🚧 Work in Progress]" + }, + { + "value": "search", + "label": "Search Keys (SearchKey with purpose_map) - Search by purpose and security level [🚧 Work in Progress]" + } + ] + }, + { + "name": "specificKeyIds", + "type": "array", + "label": "Specific Key IDs (required for 'specific' type)", + "required": false, + "placeholder": "0,1,2" + }, + { + "name": "searchPurposeMap", + "type": "text", + "label": "Search Purpose Map JSON (required for 'search' type)", + "required": false, + "placeholder": "{\"0\": {\"0\": \"current\"}, \"1\": {\"0\": \"all\"}}" + } + ] + }, + "getIdentitiesContractKeys": { + "label": "Get Identities Contract Keys", + "description": "Get keys for multiple identities related to a specific contract", + "inputs": [ + { + "name": "identitiesIds", + "type": "array", + "label": "Identity IDs", + "required": true + }, + { + "name": "contractId", + "type": "text", + "label": "Contract ID", + "required": true + }, + { + "name": "documentTypeName", + "type": "text", + "label": "Document Type (optional)", + "required": false + }, + { + "name": "keyRequestType", + "type": "select", + "label": "Key Request Type", + "required": false + } + ] + }, + "getIdentityNonce": { + "label": "Get Identity Nonce", + "description": "Get the current nonce for an identity", + "inputs": [ + { + "name": "identityId", + "type": "text", + "label": "Identity ID", + "required": true + } + ] + }, + "getIdentityContractNonce": { + "label": "Get Identity Contract Nonce", + "description": "Get the nonce for an identity in relation to a specific contract", + "inputs": [ + { + "name": "identityId", + "type": "text", + "label": "Identity ID", + "required": true + }, + { + "name": "contractId", + "type": "text", + "label": "Contract ID", + "required": true + } + ] + }, + "getIdentityBalance": { + "label": "Get Identity Balance", + "description": "Get the credit balance of an identity", + "inputs": [ + { + "name": "id", + "type": "text", + "label": "Identity ID", + "required": true + } + ] + }, + "getIdentitiesBalances": { + "label": "Get Identities Balances", + "description": "Get balances for multiple identities", + "inputs": [ + { + "name": "identityIds", + "type": "array", + "label": "Identity IDs", + "required": true + } + ] + }, + "getIdentityBalanceAndRevision": { + "label": "Get Identity Balance and Revision", + "description": "Get both balance and revision number for an identity", + "inputs": [ + { + "name": "id", + "type": "text", + "label": "Identity ID", + "required": true + } + ] + }, + "getIdentityByPublicKeyHash": { + "label": "Get Identity by Unique Public Key Hash", + "description": "Find an identity by its unique public key hash", + "inputs": [ + { + "name": "publicKeyHash", + "type": "text", + "label": "Public Key Hash", + "required": true, + "placeholder": "b7e904ce25ed97594e72f7af0e66f298031c1754" + } + ] + }, + "getIdentityByNonUniquePublicKeyHash": { + "label": "Get Identity by Non-Unique Public Key Hash", + "description": "Find identities by non-unique public key hash", + "inputs": [ + { + "name": "publicKeyHash", + "type": "text", + "label": "Public Key Hash", + "required": true, + "placeholder": "518038dc858461bcee90478fd994bba8057b7531" + } + ] + }, + "getIdentityTokenBalances": { + "label": "Get Identity Token Balances", + "description": "Get token balances for an identity", + "inputs": [ + { + "name": "identityId", + "type": "text", + "label": "Identity ID", + "required": true + }, + { + "name": "tokenIds", + "type": "array", + "label": "Token IDs", + "required": true + } + ] + }, + "getIdentitiesTokenBalances": { + "label": "Get Identities Token Balances", + "description": "Get token balance for multiple identities", + "inputs": [ + { + "name": "identityIds", + "type": "array", + "label": "Identity IDs", + "required": true + }, + { + "name": "tokenId", + "type": "text", + "label": "Token ID", + "required": true, + "placeholder": "Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv" + } + ] + }, + "getIdentityTokenInfos": { + "label": "Get Identity Token Info", + "description": "Get token information for an identity's tokens", + "inputs": [ + { + "name": "identityId", + "type": "text", + "label": "Identity ID", + "required": true + }, + { + "name": "tokenIds", + "type": "array", + "label": "Token IDs (optional)", + "required": false, + "placeholder": "[\"Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv\"]" + } + ] + }, + "getIdentitiesTokenInfos": { + "label": "Get Identities Token Info", + "description": "Get token information for multiple identities with a specific token", + "inputs": [ + { + "name": "identityIds", + "type": "array", + "label": "Identity IDs", + "required": true + }, + { + "name": "tokenId", + "type": "text", + "label": "Token ID", + "required": true, + "placeholder": "Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv" + } + ] + } + } + }, + "dataContract": { + "label": "Data Contract Queries", + "queries": { + "getDataContract": { + "label": "Get Data Contract", + "description": "Fetch a data contract by its identifier", + "inputs": [ + { + "name": "id", + "type": "text", + "label": "Data Contract ID", + "required": true, + "placeholder": "GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec" + } + ] + }, + "getDataContractHistory": { + "label": "Get Data Contract History", + "description": "Get the version history of a data contract", + "inputs": [ + { + "name": "id", + "type": "text", + "label": "Data Contract ID", + "required": true, + "placeholder": "GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec" + }, + { + "name": "limit", + "type": "number", + "label": "Limit", + "required": false + }, + { + "name": "offset", + "type": "number", + "label": "Offset", + "required": false + } + ] + }, + "getDataContracts": { + "label": "Get Data Contracts", + "description": "Fetch multiple data contracts by their identifiers", + "inputs": [ + { + "name": "ids", + "type": "array", + "label": "Data Contract IDs", + "required": true, + "placeholder": "[\"GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec\", \"ALybvzfcCwMs7sinDwmtumw17NneuW7RgFtFHgjKmF3A\"]" + } + ] + } + } + }, + "document": { + "label": "Document Queries", + "queries": { + "getDocuments": { + "label": "Get Documents", + "description": "Query documents from a data contract", + "inputs": [ + { + "name": "dataContractId", + "type": "text", + "label": "Data Contract ID", + "required": true, + "placeholder": "GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec" + }, + { + "name": "documentType", + "type": "text", + "label": "Document Type", + "required": true, + "placeholder": "domain" + }, + { + "name": "whereClause", + "type": "text", + "label": "Where Clause (JSON)", + "required": false, + "placeholder": "[[\"normalizedParentDomainName\", \"==\", \"dash\"], [\"normalizedLabel\", \"==\", \"therea1s11mshaddy5\"]]" + }, + { + "name": "orderBy", + "type": "text", + "label": "Order By (JSON)", + "required": false, + "placeholder": "[[\"$createdAt\", \"desc\"]]" + }, + { + "name": "limit", + "type": "number", + "label": "Limit", + "required": false + } + ] + }, + "getDocument": { + "label": "Get Document", + "description": "Fetch a specific document by ID", + "inputs": [ + { + "name": "dataContractId", + "type": "text", + "label": "Data Contract ID", + "required": true, + "placeholder": "GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec" + }, + { + "name": "documentType", + "type": "text", + "label": "Document Type", + "required": true, + "placeholder": "domain" + }, + { + "name": "documentId", + "type": "text", + "label": "Document ID", + "required": true, + "placeholder": "7NYmEKQsYtniQRUmxwdPGeVcirMoPh5ZPyAKz8BWFy3r" + } + ] + } + } + }, + "dpns": { + "label": "DPNS Queries", + "queries": { + "getDpnsUsername": { + "label": "Get DPNS Usernames", + "description": "Get DPNS usernames for an identity", + "inputs": [ + { + "name": "identityId", + "type": "text", + "label": "Identity ID", + "required": true + } + ] + }, + "dpnsCheckAvailability": { + "label": "DPNS Check Availability", + "description": "Check if a DPNS username is available", + "inputs": [ + { + "name": "label", + "type": "text", + "label": "Label (Username)", + "required": true + } + ] + }, + "dpnsResolve": { + "label": "DPNS Resolve Name", + "description": "Resolve a DPNS name to an identity ID", + "inputs": [ + { + "name": "name", + "type": "text", + "label": "Name", + "required": true + } + ] + } + } + }, + "voting": { + "label": "Voting & Contested Resources", + "queries": { + "getContestedResources": { + "label": "Get Contested Resources", + "description": "Get list of contested resources", + "inputs": [ + { + "name": "resultType", + "type": "select", + "label": "Result Type", + "required": true + }, + { + "name": "documentTypeName", + "type": "text", + "label": "Document Type", + "required": true + }, + { + "name": "indexName", + "type": "text", + "label": "Index Name", + "required": true + }, + { + "name": "count", + "type": "number", + "label": "Count", + "required": false + } + ] + }, + "getContestedResourceVoteState": { + "label": "Get Contested Resource Vote State", + "description": "Get the current vote state for a contested resource", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Contract ID", + "required": true + }, + { + "name": "documentTypeName", + "type": "text", + "label": "Document Type", + "required": true + }, + { + "name": "indexName", + "type": "text", + "label": "Index Name", + "required": true + } + ] + }, + "getContestedResourceVotersForIdentity": { + "label": "Get Contested Resource Voters for Identity", + "description": "Get voters who voted for a specific identity in a contested resource", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Contract ID", + "required": true + }, + { + "name": "documentTypeName", + "type": "text", + "label": "Document Type", + "required": true + }, + { + "name": "indexName", + "type": "text", + "label": "Index Name", + "required": true + }, + { + "name": "contestantId", + "type": "text", + "label": "Contestant Identity ID", + "required": true + } + ] + }, + "getContestedResourceIdentityVotes": { + "label": "Get Contested Resource Identity Votes", + "description": "Get all votes cast by a specific identity", + "inputs": [ + { + "name": "identityId", + "type": "text", + "label": "Identity ID", + "required": true + } + ] + }, + "getVotePollsByEndDate": { + "label": "Get Vote Polls by End Date", + "description": "Get vote polls within a time range", + "inputs": [ + { + "name": "startTimeMs", + "type": "number", + "label": "Start Time (ms)", + "required": true + }, + { + "name": "endTimeMs", + "type": "number", + "label": "End Time (ms)", + "required": true + } + ] + } + } + }, + "protocol": { + "label": "Protocol & Version", + "queries": { + "getProtocolVersionUpgradeState": { + "label": "Get Protocol Version Upgrade State", + "description": "Get the current state of protocol version upgrades", + "inputs": [] + }, + "getProtocolVersionUpgradeVoteStatus": { + "label": "Get Protocol Version Upgrade Vote Status", + "description": "Get voting status for protocol version upgrades", + "inputs": [ + { + "name": "startProTxHash", + "type": "text", + "label": "Start ProTx Hash", + "required": true, + "placeholder": "143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113" + }, + { + "name": "count", + "type": "number", + "label": "Count", + "required": true + } + ] + } + } + }, + "epoch": { + "label": "Epoch & Block", + "queries": { + "getEpochsInfo": { + "label": "Get Epochs Info", + "description": "Get information about epochs", + "inputs": [ + { + "name": "epoch", + "type": "number", + "label": "Start Epoch", + "required": true + }, + { + "name": "count", + "type": "number", + "label": "Count", + "required": true + }, + { + "name": "ascending", + "type": "checkbox", + "label": "Ascending Order", + "required": false + } + ] + }, + "getCurrentEpoch": { + "label": "Get Current Epoch", + "description": "Get information about the current epoch", + "inputs": [] + }, + "getFinalizedEpochInfos": { + "label": "Get Finalized Epoch Info", + "description": "Get information about finalized epochs", + "inputs": [ + { + "name": "startEpoch", + "type": "number", + "label": "Start Epoch", + "required": true + }, + { + "name": "count", + "type": "number", + "label": "Count", + "required": true + } + ] + }, + "getEvonodesProposedEpochBlocksByIds": { + "label": "Get Evonodes Proposed Epoch Blocks by IDs", + "description": "Get proposed blocks by evonode IDs", + "inputs": [ + { + "name": "ids", + "type": "array", + "label": "ProTx Hashes", + "required": true, + "placeholder": "[\"143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113\"]" + } + ] + }, + "getEvonodesProposedEpochBlocksByRange": { + "label": "Get Evonodes Proposed Epoch Blocks by Range", + "description": "Get proposed blocks by range", + "inputs": [ + { + "name": "startProTxHash", + "type": "text", + "label": "Start ProTx Hash", + "required": true, + "placeholder": "143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113" + }, + { + "name": "count", + "type": "number", + "label": "Count", + "required": true + } + ] + } + } + }, + "token": { + "label": "Token Queries", + "queries": { + "getTokenStatuses": { + "label": "Get Token Statuses", + "description": "Get token statuses", + "inputs": [ + { + "name": "tokenIds", + "type": "array", + "label": "Token IDs", + "required": true + } + ] + }, + "getTokenDirectPurchasePrices": { + "label": "Get Token Direct Purchase Prices", + "description": "Get direct purchase prices for tokens", + "inputs": [ + { + "name": "tokenIds", + "type": "array", + "label": "Token IDs", + "required": true + } + ] + }, + "getTokenContractInfo": { + "label": "Get Token Contract Info", + "description": "Get information about a token contract", + "inputs": [ + { + "name": "dataContractId", + "type": "text", + "label": "Data Contract ID", + "required": true, + "placeholder": "EETVvWgohFDKtbB3ejEzBcDRMNYkc9TtgXY6y8hzP3Ta" + } + ] + }, + "getTokenPerpetualDistributionLastClaim": { + "label": "Get Token Perpetual Distribution Last Claim", + "description": "Get last claim information for perpetual distribution", + "inputs": [ + { + "name": "identityId", + "type": "text", + "label": "Identity ID", + "required": true + }, + { + "name": "tokenId", + "type": "text", + "label": "Token ID", + "required": true + } + ] + }, + "getTokenTotalSupply": { + "label": "Get Token Total Supply", + "description": "Get total supply of a token", + "inputs": [ + { + "name": "tokenId", + "type": "text", + "label": "Token ID", + "required": true, + "placeholder": "Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv" + } + ] + } + } + }, + "group": { + "label": "Group Queries", + "queries": { + "getGroupInfo": { + "label": "Get Group Info", + "description": "Get information about a group", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Contract ID", + "required": true + }, + { + "name": "groupContractPosition", + "type": "number", + "label": "Group Contract Position", + "required": true + } + ] + }, + "getGroupInfos": { + "label": "Get Group Infos", + "description": "Get information about multiple groups", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Contract ID", + "required": true + }, + { + "name": "startAtGroupContractPosition", + "type": "number", + "label": "Start at Position", + "required": false + }, + { + "name": "startGroupContractPositionIncluded", + "type": "checkbox", + "label": "Include Start Position", + "required": false + }, + { + "name": "count", + "type": "number", + "label": "Count", + "required": false + } + ] + }, + "getGroupActions": { + "label": "Get Group Actions", + "description": "Get actions for a group", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Contract ID", + "required": true + }, + { + "name": "groupContractPosition", + "type": "number", + "label": "Group Contract Position", + "required": true + }, + { + "name": "status", + "type": "select", + "label": "Status", + "required": true, + "options": [ + { + "value": "ACTIVE", + "label": "Active" + }, + { + "value": "CLOSED", + "label": "Closed" + } + ] + }, + { + "name": "startActionId", + "type": "text", + "label": "Start Action ID", + "required": false + }, + { + "name": "startActionIdIncluded", + "type": "checkbox", + "label": "Include Start Action", + "required": false + }, + { + "name": "count", + "type": "number", + "label": "Count", + "required": false + } + ] + }, + "getGroupActionSigners": { + "label": "Get Group Action Signers", + "description": "Get signers for a group action", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Contract ID", + "required": true + }, + { + "name": "groupContractPosition", + "type": "number", + "label": "Group Contract Position", + "required": true + }, + { + "name": "status", + "type": "select", + "label": "Status", + "required": true, + "options": [ + { + "value": "ACTIVE", + "label": "Active" + }, + { + "value": "CLOSED", + "label": "Closed" + } + ] + }, + { + "name": "actionId", + "type": "text", + "label": "Action ID", + "required": true + } + ] + } + } + }, + "system": { + "label": "System & Utility", + "queries": { + "getStatus": { + "label": "Get Status", + "description": "Get system status", + "inputs": [] + }, + "getCurrentQuorumsInfo": { + "label": "Get Current Quorums Info", + "description": "Get information about current quorums", + "inputs": [] + }, + "getPrefundedSpecializedBalance": { + "label": "Get Prefunded Specialized Balance", + "description": "Get prefunded specialized balance", + "inputs": [ + { + "name": "identityId", + "type": "text", + "label": "Specialized Balance ID", + "required": true, + "placeholder": "AzaU7zqCT7X1kxh8yWxkT9PxAgNqWDu4Gz13emwcRyAT" + } + ] + }, + "getTotalCreditsInPlatform": { + "label": "Get Total Credits in Platform", + "description": "Get total credits in the platform", + "inputs": [] + }, + "getPathElements": { + "label": "Get Path Elements", + "description": "Access any data in the Dash Platform state tree. This low-level query allows direct access to GroveDB storage by specifying a path through the tree structure and keys to retrieve at that path. Common paths include: Identities (32), Tokens (96), DataContractDocuments (64), Balances (16), Votes (80), and more.", + "inputs": [ + { + "name": "path", + "type": "array", + "label": "Path", + "required": true + }, + { + "name": "keys", + "type": "array", + "label": "Keys", + "required": true + } + ] + }, + "waitForStateTransitionResult": { + "label": "Wait for State Transition Result", + "description": "Internal query to wait for and retrieve the result of a previously submitted state transition", + "inputs": [ + { + "name": "stateTransitionHash", + "type": "text", + "label": "State Transition Hash", + "required": true + } + ] + } + } + } + }, + "transitions": { + "identity": { + "label": "Identity Transitions", + "transitions": { + "identityCreate": { + "label": "Identity Create", + "description": "Create a new identity with initial credits", + "inputs": [ + { + "name": "publicKeys", + "type": "keyArray", + "label": "Public Keys", + "required": true + }, + { + "name": "assetLockProof", + "type": "assetLockProof", + "label": "Asset Lock Proof", + "required": true + } + ] + }, + "identityTopUp": { + "label": "Identity Top Up", + "description": "Add credits to an existing identity", + "inputs": [ + { + "name": "assetLockProof", + "type": "assetLockProof", + "label": "Asset Lock Proof", + "required": true + } + ] + }, + "identityUpdate": { + "label": "Identity Update", + "description": "Update identity keys (add or disable)", + "inputs": [ + { + "name": "addPublicKeys", + "type": "textarea", + "label": "Keys to Add (JSON array)", + "required": false, + "placeholder": "[{\"keyType\":\"ECDSA_HASH160\",\"purpose\":\"AUTHENTICATION\",\"data\":\"base64_key_data\"}]" + }, + { + "name": "disablePublicKeys", + "type": "text", + "label": "Key IDs to Disable (comma-separated)", + "required": false, + "placeholder": "2,3,5" + } + ] + }, + "identityCreditTransfer": { + "label": "Identity Credit Transfer", + "description": "Transfer credits between identities", + "inputs": [ + { + "name": "recipientId", + "type": "text", + "label": "Recipient Identity ID", + "required": true + }, + { + "name": "amount", + "type": "number", + "label": "Amount (credits)", + "required": true + } + ] + }, + "identityCreditWithdrawal": { + "label": "Identity Credit Withdrawal", + "description": "Withdraw credits from identity to Dash address", + "inputs": [ + { + "name": "toAddress", + "type": "text", + "label": "Dash Address", + "required": true + }, + { + "name": "amount", + "type": "number", + "label": "Amount (credits)", + "required": true + }, + { + "name": "coreFeePerByte", + "type": "number", + "label": "Core Fee Per Byte (optional)", + "required": false + } + ] + } + } + }, + "dataContract": { + "label": "Data Contract Transitions", + "transitions": { + "dataContractCreate": { + "label": "Data Contract Create", + "description": "Create a new data contract", + "inputs": [ + { + "name": "canBeDeleted", + "type": "checkbox", + "label": "Can Be Deleted", + "required": false + }, + { + "name": "readonly", + "type": "checkbox", + "label": "Read Only", + "required": false + }, + { + "name": "keepsHistory", + "type": "checkbox", + "label": "Keeps History", + "required": false + }, + { + "name": "documentsKeepHistoryContractDefault", + "type": "checkbox", + "label": "Documents Keep History (Default)", + "required": false + }, + { + "name": "documentsMutableContractDefault", + "type": "checkbox", + "label": "Documents Mutable (Default)", + "required": false, + "defaultValue": true + }, + { + "name": "documentsCanBeDeletedContractDefault", + "type": "checkbox", + "label": "Documents Can Be Deleted (Default)", + "required": false, + "defaultValue": true + }, + { + "name": "requiresIdentityEncryptionBoundedKey", + "type": "text", + "label": "Requires Identity Encryption Key (optional)", + "required": false + }, + { + "name": "requiresIdentityDecryptionBoundedKey", + "type": "text", + "label": "Requires Identity Decryption Key (optional)", + "required": false + }, + { + "name": "documentSchemas", + "type": "json", + "label": "Document Schemas JSON", + "required": true, + "placeholder": "{\n \"note\": {\n \"type\": \"object\",\n \"properties\": {\n \"message\": {\n \"type\": \"string\",\n \"maxLength\": 100,\n \"position\": 0\n }\n },\n \"required\": [\"message\"],\n \"additionalProperties\": false\n }\n}" + }, + { + "name": "groups", + "type": "json", + "label": "Groups (optional)", + "required": false, + "placeholder": "{}" + }, + { + "name": "tokens", + "type": "json", + "label": "Tokens (optional)", + "required": false, + "placeholder": "{}" + }, + { + "name": "keywords", + "type": "text", + "label": "Keywords (comma separated, optional)", + "required": false + }, + { + "name": "description", + "type": "text", + "label": "Description (optional)", + "required": false + } + ] + }, + "dataContractUpdate": { + "label": "Data Contract Update", + "description": "Add document types, groups, or tokens to an existing data contract", + "inputs": [ + { + "name": "dataContractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "newDocumentSchemas", + "type": "json", + "label": "New Document Schemas to Add (optional)", + "required": false, + "placeholder": "{\n \"newType\": {\n \"type\": \"object\",\n \"properties\": {\n \"field\": {\n \"type\": \"string\",\n \"maxLength\": 100,\n \"position\": 0\n }\n },\n \"required\": [\"field\"],\n \"additionalProperties\": false\n }\n}" + }, + { + "name": "newGroups", + "type": "json", + "label": "New Groups to Add (optional)", + "required": false, + "placeholder": "{}" + }, + { + "name": "newTokens", + "type": "json", + "label": "New Tokens to Add (optional)", + "required": false, + "placeholder": "{}" + } + ] + } + } + }, + "document": { + "label": "Document Transitions", + "transitions": { + "documentCreate": { + "label": "Document Create", + "description": "Create a new document", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "documentType", + "type": "text", + "label": "Document Type", + "required": true + }, + { + "name": "fetchSchema", + "type": "button", + "label": "Fetch Schema", + "action": "fetchDocumentSchema" + }, + { + "name": "documentFields", + "type": "dynamic", + "label": "Document Fields" + } + ] + }, + "documentReplace": { + "label": "Document Replace", + "description": "Replace an existing document", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "documentType", + "type": "text", + "label": "Document Type", + "required": true + }, + { + "name": "documentId", + "type": "text", + "label": "Document ID", + "required": true + }, + { + "name": "loadDocument", + "type": "button", + "label": "Load Document", + "action": "loadExistingDocument" + }, + { + "name": "documentFields", + "type": "dynamic", + "label": "Document Fields" + } + ] + }, + "documentDelete": { + "label": "Document Delete", + "description": "Delete an existing document", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "documentType", + "type": "text", + "label": "Document Type", + "required": true + }, + { + "name": "documentId", + "type": "text", + "label": "Document ID", + "required": true + } + ] + }, + "documentTransfer": { + "label": "Document Transfer", + "description": "Transfer document ownership", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "documentType", + "type": "text", + "label": "Document Type", + "required": true + }, + { + "name": "documentId", + "type": "text", + "label": "Document ID", + "required": true + }, + { + "name": "recipientId", + "type": "text", + "label": "Recipient Identity ID", + "required": true + } + ] + }, + "documentPurchase": { + "label": "Document Purchase", + "description": "Purchase a document", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "documentType", + "type": "text", + "label": "Document Type", + "required": true + }, + { + "name": "documentId", + "type": "text", + "label": "Document ID", + "required": true + }, + { + "name": "price", + "type": "number", + "label": "Price (credits)", + "required": true + } + ] + }, + "documentSetPrice": { + "label": "Document Set Price", + "description": "Set or update document price", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "documentType", + "type": "text", + "label": "Document Type", + "required": true + }, + { + "name": "documentId", + "type": "text", + "label": "Document ID", + "required": true + }, + { + "name": "price", + "type": "number", + "label": "Price (credits, 0 to remove)", + "required": true + } + ] + }, + "dpnsRegister": { + "label": "DPNS Register Name", + "description": "Register a new DPNS username", + "inputs": [ + { + "name": "label", + "type": "text", + "label": "Username", + "required": true, + "placeholder": "Enter username (e.g., alice)", + "validateOnType": true + } + ] + } + } + }, + "token": { + "label": "Token Transitions", + "transitions": { + "tokenBurn": { + "label": "Token Burn", + "description": "Burn tokens", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "tokenPosition", + "type": "number", + "label": "Token Contract Position", + "required": true + }, + { + "name": "amount", + "type": "text", + "label": "Amount to Burn", + "required": true + }, + { + "name": "keyId", + "type": "number", + "label": "Key ID (for signing)", + "required": true + }, + { + "name": "publicNote", + "type": "text", + "label": "Public Note", + "required": false + } + ] + }, + "tokenMint": { + "label": "Token Mint", + "description": "Mint new tokens", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "tokenPosition", + "type": "number", + "label": "Token Contract Position", + "required": true + }, + { + "name": "amount", + "type": "text", + "label": "Amount to Mint", + "required": true + }, + { + "name": "keyId", + "type": "number", + "label": "Key ID (for signing)", + "required": true + }, + { + "name": "issuedToIdentityId", + "type": "text", + "label": "Issue To Identity ID", + "required": false + }, + { + "name": "publicNote", + "type": "text", + "label": "Public Note", + "required": false + } + ] + }, + "tokenTransfer": { + "label": "Token Transfer", + "description": "Transfer tokens to another identity", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "tokenId", + "type": "text", + "label": "Token Contract Position", + "required": true + }, + { + "name": "amount", + "type": "number", + "label": "Amount to Transfer", + "required": true + }, + { + "name": "recipientId", + "type": "text", + "label": "Recipient Identity ID", + "required": true + } + ] + }, + "tokenFreeze": { + "label": "Token Freeze", + "description": "Freeze tokens for an identity", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "tokenId", + "type": "text", + "label": "Token Contract Position", + "required": true + }, + { + "name": "identityId", + "type": "text", + "label": "Identity ID to Freeze", + "required": true + } + ] + }, + "tokenUnfreeze": { + "label": "Token Unfreeze", + "description": "Unfreeze tokens for an identity", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "tokenId", + "type": "text", + "label": "Token Contract Position", + "required": true + }, + { + "name": "identityId", + "type": "text", + "label": "Identity ID to Unfreeze", + "required": true + } + ] + }, + "tokenDestroyFrozen": { + "label": "Token Destroy Frozen Funds", + "description": "Destroy frozen tokens", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true + }, + { + "name": "tokenId", + "type": "text", + "label": "Token Contract Position", + "required": true + }, + { + "name": "identityId", + "type": "text", + "label": "Identity ID", + "required": true + } + ] + } + } + }, + "voting": { + "label": "Voting Transitions", + "transitions": { + "dpnsUsername": { + "label": "DPNS Username", + "description": "Cast a vote for a contested DPNS username", + "inputs": [ + { + "name": "contestedUsername", + "type": "text", + "label": "Contested Username", + "required": true, + "placeholder": "Enter the contested username (e.g., 'myusername')" + }, + { + "name": "voteChoice", + "type": "select", + "label": "Vote Choice", + "required": true, + "options": [ + { + "value": "abstain", + "label": "Abstain" + }, + { + "value": "lock", + "label": "Lock (Give to no one)" + }, + { + "value": "towardsIdentity", + "label": "Vote for Identity" + } + ] + }, + { + "name": "targetIdentity", + "type": "text", + "label": "Target Identity ID (if voting for identity)", + "required": false, + "placeholder": "Identity ID to vote for", + "dependsOn": { + "field": "voteChoice", + "value": "towardsIdentity" + } + } + ] + }, + "masternodeVote": { + "label": "Contested Resource", + "description": "Cast a vote for contested resources as a masternode", + "inputs": [ + { + "name": "contractId", + "type": "text", + "label": "Data Contract ID", + "required": true, + "placeholder": "Contract ID containing the contested resource" + }, + { + "name": "fetchContestedResources", + "type": "button", + "label": "Get Contested Resources", + "action": "fetchContestedResources" + }, + { + "name": "contestedResourceDropdown", + "type": "dynamic", + "label": "Contested Resources" + }, + { + "name": "voteChoice", + "type": "select", + "label": "Vote Choice", + "required": true, + "options": [ + { + "value": "abstain", + "label": "Abstain" + }, + { + "value": "lock", + "label": "Lock (Give to no one)" + }, + { + "value": "towardsIdentity", + "label": "Vote for Identity" + } + ] + }, + { + "name": "targetIdentity", + "type": "text", + "label": "Target Identity ID (if voting for identity)", + "required": false, + "placeholder": "Identity ID to vote for", + "dependsOn": { + "field": "voteChoice", + "value": "towardsIdentity" + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/packages/wasm-sdk/generate_docs.py b/packages/wasm-sdk/generate_docs.py new file mode 100755 index 00000000000..7eaf35a2707 --- /dev/null +++ b/packages/wasm-sdk/generate_docs.py @@ -0,0 +1,1791 @@ +#!/usr/bin/env python3 +""" +Documentation generator for WASM JS SDK +Extracts query and state transition definitions from index.html +and generates both user documentation (HTML) and AI reference (Markdown) +""" + +import os +import re +import json +import html +from pathlib import Path +from datetime import datetime + +def extract_definitions_from_html(html_content): + """Extract query and state transition definitions from index.html""" + + # Extract queryDefinitions + query_match = re.search(r'const queryDefinitions = ({[\s\S]*?});(?=\s*(?:const|//|$))', html_content) + query_definitions = {} + if query_match: + # Clean up the JavaScript object to make it JSON-parseable + query_str = query_match.group(1) + # Convert JS object to JSON format + query_str = re.sub(r'(\w+):', r'"\1":', query_str) # Add quotes to keys + query_str = re.sub(r',\s*}', '}', query_str) # Remove trailing commas + query_str = re.sub(r',\s*]', ']', query_str) # Remove trailing commas in arrays + # Handle functions and complex values + query_str = re.sub(r'dependsOn:\s*{[^}]+}', '"dependsOn": {}', query_str) + query_str = re.sub(r'action:\s*"[^"]*"', '"action": ""', query_str) + query_str = re.sub(r'dynamic:\s*true', '"dynamic": true', query_str) + query_str = re.sub(r'defaultValue:\s*true', '"defaultValue": true', query_str) + query_str = re.sub(r'validateOnType:\s*true', '"validateOnType": true', query_str) + + try: + query_definitions = json.loads(query_str) + except json.JSONDecodeError as e: + print(f"Warning: Could not parse query definitions: {e}") + # Fallback to regex extraction + query_definitions = extract_definitions_regex(html_content, 'queryDefinitions') + + # Extract stateTransitionDefinitions + transition_match = re.search(r'const stateTransitionDefinitions = ({[\s\S]*?});(?=\s*(?:const|//|$))', html_content) + transition_definitions = {} + if transition_match: + trans_str = transition_match.group(1) + trans_str = re.sub(r'(\w+):', r'"\1":', trans_str) + trans_str = re.sub(r',\s*}', '}', trans_str) + trans_str = re.sub(r',\s*]', ']', trans_str) + trans_str = re.sub(r'dependsOn:\s*{[^}]+}', '"dependsOn": {}', trans_str) + trans_str = re.sub(r'action:\s*"[^"]*"', '"action": ""', trans_str) + trans_str = re.sub(r'dynamic:\s*true', '"dynamic": true', trans_str) + trans_str = re.sub(r'defaultValue:\s*true', '"defaultValue": true', trans_str) + trans_str = re.sub(r'validateOnType:\s*true', '"validateOnType": true', trans_str) + + try: + transition_definitions = json.loads(trans_str) + except json.JSONDecodeError as e: + print(f"Warning: Could not parse transition definitions: {e}") + transition_definitions = extract_definitions_regex(html_content, 'stateTransitionDefinitions') + + return query_definitions, transition_definitions + +def extract_definitions_regex(html_content, definition_name): + """Robust regex extraction method for JavaScript object definitions""" + definitions = {} + + # Find the complete definition block + pattern = rf'const {definition_name} = (\{{(?:[^{{}}]|{{[^{{}}]*}})*\}});' + match = re.search(pattern, html_content, re.DOTALL) + if not match: + return definitions + + full_def = match.group(1) + + # Extract each category + cat_pattern = r'(\w+):\s*\{[^}]*label:\s*"([^"]+)"[^}]*(?:queries|transitions):\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}' + + for cat_match in re.finditer(cat_pattern, full_def, re.DOTALL): + cat_key = cat_match.group(1) + cat_label = cat_match.group(2) + items_block = cat_match.group(3) + + items_key = 'queries' if 'query' in definition_name else 'transitions' + definitions[cat_key] = { + 'label': cat_label, + items_key: {} + } + + # Extract individual queries/transitions + item_pattern = r'(\w+):\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}' + + for item_match in re.finditer(item_pattern, items_block): + item_key = item_match.group(1) + item_content = item_match.group(2) + + # Extract item details + item_data = {} + + # Extract label + label_match = re.search(r'label:\s*"([^"]+)"', item_content) + if label_match: + item_data['label'] = label_match.group(1) + + # Extract description + desc_match = re.search(r'description:\s*"([^"]+)"', item_content) + if desc_match: + item_data['description'] = desc_match.group(1) + + # Extract inputs array + inputs_match = re.search(r'inputs:\s*\[([^\]]+(?:\[[^\]]*\][^\]]*)*)\]', item_content, re.DOTALL) + if inputs_match: + inputs_str = inputs_match.group(1) + item_data['inputs'] = extract_inputs(inputs_str) + else: + item_data['inputs'] = [] + + definitions[cat_key][items_key][item_key] = item_data + + return definitions + +def generate_example_code(query_key, inputs): + """Generate example code for a query""" + + # Test data for various query types + # Using a known testnet identity with activity + test_data = { + 'identity_id': '5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk', + 'specialized_balance_id': 'AzaU7zqCT7X1kxh8yWxkT9PxAgNqWDu4Gz13emwcRyAT', + 'contract_id': 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + 'data_contract_id': 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + 'token_contract_id': 'ALybvzfcCwMs7sinDwmtumw17NneuW7RgFtFHgjKmF3A', + 'group_contract_id': '49PJEnNx7ReCitzkLdkDNr4s6RScGsnNexcdSZJ1ph5N', + 'public_key_hash_unique': 'b7e904ce25ed97594e72f7af0e66f298031c1754', + 'public_key_hash_non_unique': '518038dc858461bcee90478fd994bba8057b7531', + 'pro_tx_hash': '143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113', + 'token_id': 'Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv', + 'document_type': 'domain', + 'document_id': '7NYmEKQsYtniQRUmxwdPGeVcirMoPh5ZPyAKz8BWFy3r', + 'username': 'alice', + 'epoch': 8635 + } + + # Map input names to test values + param_mapping = { + 'id': f"'{test_data['data_contract_id']}'" if 'getDataContract' in query_key else f"'{test_data['identity_id']}'", + 'identityId': f"'{test_data['specialized_balance_id']}'" if 'getPrefundedSpecializedBalance' in query_key else f"'{test_data['identity_id']}'", + 'ids': f"['{test_data['data_contract_id']}', '{test_data['token_contract_id']}']" if 'getDataContracts' in query_key else f"['{test_data['pro_tx_hash']}']" if 'Evonodes' in query_key else f"['{test_data['identity_id']}']", + 'identitiesIds': f"['{test_data['identity_id']}']", + 'identityIds': f"['{test_data['identity_id']}']", + 'contractId': f"'{test_data['group_contract_id']}'" if ('group' in query_key.lower() or 'Group' in query_key) else f"'{test_data['token_contract_id']}'" if ('token' in query_key.lower() or 'Token' in query_key) and 'TokenBalance' not in query_key and 'TokenInfo' not in query_key else f"'{test_data['contract_id']}'", + 'dataContractId': "'EETVvWgohFDKtbB3ejEzBcDRMNYkc9TtgXY6y8hzP3Ta'" if 'getTokenContractInfo' in query_key else f"'{test_data['data_contract_id']}'", + 'publicKeyHash': f"'{test_data['public_key_hash_unique']}'" if 'ByPublicKeyHash' in query_key and 'NonUnique' not in query_key else f"'{test_data['public_key_hash_non_unique']}'", + 'startProTxHash': f"'{test_data['pro_tx_hash']}'", + 'tokenId': "'EETVvWgohFDKtbB3ejEzBcDRMNYkc9TtgXY6y8hzP3Ta'" if 'getTokenPerpetualDistributionLastClaim' in query_key else f"'{test_data['token_id']}'", + 'tokenIds': f"['{test_data['token_id']}', 'H7FRpZJqZK933r9CzZMsCuf1BM34NT5P2wSJyjDkprqy']" if 'getTokenStatuses' in query_key else "['H7FRpZJqZK933r9CzZMsCuf1BM34NT5P2wSJyjDkprqy']" if 'getTokenDirectPurchasePrices' in query_key else f"['{test_data['token_id']}']", + 'documentType': f"'{test_data['document_type']}'", + 'documentId': f"'{test_data['document_id']}'", + 'label': f"'{test_data['username']}'", + 'name': f"'{test_data['username']}'", + 'epoch': '1000' if 'getEpochsInfo' in query_key else test_data['epoch'], + 'keyRequestType': "'all'", + 'limit': '10', + 'count': '100', + 'offset': '0', + 'startEpoch': '8635', + 'startTimeMs': 'Date.now() - 86400000', # 24 hours ago + 'endTimeMs': 'Date.now()', + 'ascending': 'true', + 'orderAscending': 'true', + 'resultType': "'documents'", + 'documentTypeName': "'domain'", + 'indexName': "'parentNameAndLabel'", + 'contestantId': f"'{test_data['identity_id']}'", + 'amount': '1000000', + 'recipientId': f"'{test_data['identity_id']}'", + 'toAddress': "'yNPbcFfabtNmmxKdGwhHomdYfVs6gikbPf'", + 'whereClause': 'JSON.stringify([["normalizedParentDomainName", "==", "dash"]])', + 'orderBy': 'JSON.stringify([["normalizedLabel", "asc"]])', + 'groupContractPosition': '0', + 'groupContractPositions': '[0]', + 'startAtGroupContractPosition': '0', + 'startGroupContractPositionIncluded': 'false', + 'status': "'ACTIVE'", + 'startActionId': "'0'", + 'startActionIdIncluded': 'false', + 'actionId': "'6XJzL6Qb8Zhwxt4HFwh8NAn7q1u4dwdoUf8EmgzDudFZ'", + 'path': "['96']", + 'keys': f"['{test_data['identity_id']}']", + 'stateTransitionHash': "'0000000000000000000000000000000000000000000000000000000000000000'" + } + + # Handle special cases for functions with structured parameters + if query_key == 'getGroupInfos': + # getGroupInfos expects: sdk, contractId, startAtInfo (object or null), count + params = [f"'{test_data['group_contract_id']}'", "null", "100"] + elif query_key == 'getGroupActions': + # getGroupActions expects: sdk, contractId, groupContractPosition, status, startAtInfo (object or null), count + params = [f"'{test_data['group_contract_id']}'", "0", "'ACTIVE'", "null", "100"] + else: + # Generate parameters normally + params = [] + for input_def in inputs: + name = input_def.get('name', '') + if name in param_mapping: + params.append(str(param_mapping[name])) + elif input_def.get('required', False): + # Generate a default value based on type + if input_def.get('type') == 'array': + params.append('[]') + elif input_def.get('type') == 'number': + params.append('100') + elif input_def.get('type') == 'checkbox': + params.append('false') + else: + params.append('""') + + # Handle special function name mappings + func_name_map = { + 'getIdentity': 'identity_fetch', + 'getIdentityKeys': 'get_identity_keys', + 'getIdentitiesContractKeys': 'get_identities_contract_keys', + 'getIdentityNonce': 'get_identity_nonce', + 'getIdentityContractNonce': 'get_identity_contract_nonce', + 'getIdentityBalance': 'get_identity_balance', + 'getIdentitiesBalances': 'get_identities_balances', + 'getIdentityBalanceAndRevision': 'get_identity_balance_and_revision', + 'getIdentityByPublicKeyHash': 'get_identity_by_public_key_hash', + 'getIdentityByNonUniquePublicKeyHash': 'get_identity_by_non_unique_public_key_hash', + 'getDataContract': 'data_contract_fetch', + 'getDataContractHistory': 'get_data_contract_history', + 'getDataContracts': 'get_data_contracts', + 'getDocuments': 'get_documents', + 'getDocument': 'get_document', + 'getDpnsUsername': 'get_dpns_usernames', + 'dpnsCheckAvailability': 'dpns_is_name_available', + 'dpnsResolve': 'dpns_resolve_name', + 'getContestedResources': 'get_contested_resources', + 'getContestedResourceVoteState': 'get_contested_resource_vote_state', + 'getContestedResourceVotersForIdentity': 'get_contested_resource_voters_for_identity', + 'getContestedResourceIdentityVotes': 'get_contested_resource_identity_votes', + 'getVotePollsByEndDate': 'get_vote_polls_by_end_date', + 'getProtocolVersionUpgradeState': 'get_protocol_version_upgrade_state', + 'getProtocolVersionUpgradeVoteStatus': 'get_protocol_version_upgrade_vote_status', + 'getEpochsInfo': 'get_epochs_info', + 'getCurrentEpoch': 'get_current_epoch', + 'getFinalizedEpochInfos': 'get_finalized_epoch_infos', + 'getEvonodesProposedEpochBlocksByIds': 'get_evonodes_proposed_epoch_blocks_by_ids', + 'getEvonodesProposedEpochBlocksByRange': 'get_evonodes_proposed_epoch_blocks_by_range', + 'getIdentityTokenBalances': 'get_identity_token_balances', + 'getIdentitiesTokenBalances': 'get_identities_token_balances', + 'getIdentityTokenInfos': 'get_identity_token_infos', + 'getIdentitiesTokenInfos': 'get_identities_token_infos', + 'getTokenStatuses': 'get_token_statuses', + 'getTokenDirectPurchasePrices': 'get_token_direct_purchase_prices', + 'getTokenContractInfo': 'get_token_contract_info', + 'getTokenPerpetualDistributionLastClaim': 'get_token_perpetual_distribution_last_claim', + 'getTokenTotalSupply': 'get_token_total_supply', + 'getGroupInfo': 'get_group_info', + 'getGroupInfos': 'get_group_infos', + 'getGroupActions': 'get_group_actions', + 'getGroupActionSigners': 'get_group_action_signers', + 'getStatus': 'get_status', + 'getCurrentQuorumsInfo': 'get_current_quorums_info', + 'getPrefundedSpecializedBalance': 'get_prefunded_specialized_balance', + 'getTotalCreditsInPlatform': 'get_total_credits_in_platform', + 'getPathElements': 'get_path_elements', + 'waitForStateTransitionResult': 'wait_for_state_transition_result' + } + + func_name = func_name_map.get(query_key, query_key) + + # Add sdk as first parameter for all functions + all_params = ['sdk'] + params + + # Generate the function call (functions are imported directly, not methods on sdk) + return f'return await window.wasmFunctions.{func_name}({", ".join(all_params)});' + +def extract_inputs(inputs_str): + """Extract input definitions from JavaScript array string""" + inputs = [] + + # Match individual input objects + input_pattern = r'\{([^}]+(?:\{[^}]*\}[^}]*)*)\}' + + for match in re.finditer(input_pattern, inputs_str): + input_content = match.group(1) + input_data = {} + + # Extract name + name_match = re.search(r'name:\s*"([^"]+)"', input_content) + if name_match: + input_data['name'] = name_match.group(1) + + # Extract type + type_match = re.search(r'type:\s*"([^"]+)"', input_content) + if type_match: + input_data['type'] = type_match.group(1) + + # Extract label + label_match = re.search(r'label:\s*"([^"]+)"', input_content) + if label_match: + input_data['label'] = label_match.group(1) + + # Extract required + req_match = re.search(r'required:\s*(true|false)', input_content) + if req_match: + input_data['required'] = req_match.group(1) == 'true' + + # Extract placeholder + placeholder_match = re.search(r'placeholder:\s*["\']([^"\']+)["\']', input_content) + if placeholder_match: + input_data['placeholder'] = placeholder_match.group(1) + + # Extract options if present + options_match = re.search(r'options:\s*\[([^\]]+)\]', input_content) + if options_match: + options_str = options_match.group(1) + input_data['options'] = [] + + # Extract each option + opt_pattern = r'\{\s*value:\s*"([^"]+)"[^}]*label:\s*"([^"]+)"[^}]*\}' + for opt_match in re.finditer(opt_pattern, options_str): + input_data['options'].append({ + 'value': opt_match.group(1), + 'label': opt_match.group(2) + }) + + if input_data: + inputs.append(input_data) + + return inputs + +def generate_sidebar_entries(definitions, type_prefix, section_class=""): + """Generate sidebar entries for queries or transitions""" + html = "" + for cat_key, category in definitions.items(): + html += f'
  • {category.get("label", cat_key)}
  • \n' + items = category.get('queries' if type_prefix == 'query' else 'transitions', {}) + for item_key in items: + item = items[item_key] + html += f'
  • {item.get("label", item_key)}
  • \n' + return html + +def generate_operation_docs(definitions, type_name, type_prefix): + """Generate documentation for operations (queries or transitions)""" + html = "" + for cat_key, category in definitions.items(): + html += f'''\n
    +

    {category.get('label', cat_key)}

    +''' + + items_key = 'queries' if type_prefix == 'query' else 'transitions' + items = category.get(items_key, {}) + for item_key, item in items.items(): + html += generate_operation_entry(item_key, item, type_prefix) + + html += '
    ' + return html + +def generate_operation_entry(operation_key, operation, type_prefix): + """Generate documentation for a single operation""" + html = f'''
    +

    {operation.get('label', operation_key)}

    +

    {operation.get('description', 'No description available')}

    + +
    +
    Parameters:
    +''' + + inputs = operation.get('inputs', []) + if not inputs: + html += '

    No parameters required

    ' + else: + for param in inputs: + html += generate_parameter_entry(param) + + html += '''
    + +
    +
    Example
    +''' + + if type_prefix == 'query': + example_code = generate_example_code(operation_key, inputs) + html += f'
    {example_code}
    \n' + + # Special handling for certain operations + if operation_key == 'waitForStateTransitionResult': + html += '

    This is an internal query used to wait for and retrieve the result of a previously submitted state transition. It requires a valid state transition hash from a prior operation.

    ' + else: + html += f' ' + if operation_key in ['getPathElements', 'getDataContractHistory', 'getContestedResourceVotersForIdentity', 'getTokenPerpetualDistributionLastClaim']: + html += ' 🚧 Work in Progress' + + # Add special examples and info + if operation_key == 'getIdentityKeys': + html += '''\n
    +
    Example 2 - Get Specific Keys
    +
    return await window.wasmFunctions.get_identity_keys(sdk, \'5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk\', \'specific\', [0, 1, 2]);
    + +
    +
    ''' + elif operation_key == 'getPathElements': + html += generate_path_elements_info() + + html += f'\n
    ' + else: + # State transitions don't have run buttons + html += f'
    {generate_transition_example(operation_key)}
    ' + + html += '''
    +
    +''' + return html + +def generate_parameter_entry(param): + """Generate documentation for a single parameter""" + required_text = '(required)' if param.get('required', False) else '(optional)' + html = f'''
    + {param.get('label', param.get('name', 'Unknown'))} + {param.get('type', 'text')} + {required_text} +''' + if param.get('placeholder'): + html += f'
    Example: {html.escape(param.get("placeholder"))}\n' + elif param.get('name') == 'limit' and not param.get('required', False): + html += '
    Default: 100 (maximum items returned if not specified)\n' + if param.get('options'): + html += '
    Options: ' + opts = [f'{opt.get("label", opt.get("value"))}' for opt in param.get('options', [])] + html += ', '.join(opts) + html += '\n' + html += '
    \n' + return html + +def generate_transition_example(trans_key): + """Generate example code for state transitions""" + if trans_key == 'documentCreate': + return '''const result = await sdk.document_create( + identityHex, + contractId, + "note", + JSON.stringify({ message: "Hello!" }), + privateKeyHex +);''' + elif trans_key == 'tokenTransfer': + return '''const result = await sdk.token_transfer( + identityHex, + contractId, + tokenId, + 1000000, // amount + recipientId, + privateKeyHex +);''' + else: + return f'const result = await sdk.{trans_key}(identityHex, /* params */, privateKeyHex);' + +def generate_path_elements_info(): + """Generate path elements documentation""" + return '''\n
    +
    Common Path Values:
    + + + + + + + + + + + + + + + + +
    Path ValueDescription
    64Data Contract Documents
    32Identities
    24Unique Public Key Hashes to Identities
    8Non-Unique Public Key Hashes to Identities
    16Tokens
    48Pools
    40Prefunded Specialized Balances
    72Spent Asset Lock Transactions
    80Withdrawal Transactions
    88Group Actions
    96Balances
    104Misc
    112Votes
    120Versions
    +
    Example Paths:
    + +
    ''' + +def generate_user_docs_html(query_defs, transition_defs): + """Generate user-friendly HTML documentation""" + + html_content = ''' + + + + + Dash Platform WASM JS SDK Documentation + + + + + + + +
    +
    +
    Loading WASM module...
    +
    +
    +
    +
    +
    0%
    +
    +
    +
    + + + + + +
    + + +

    Dash Platform WASM JS SDK Documentation

    + +
    +

    Overview

    +

    The Dash Platform WASM JS SDK provides a WebAssembly-based interface for interacting with the Dash Platform from JavaScript and TypeScript applications. + This documentation covers all available queries and state transitions.

    + +

    Key Concepts

    + + +

    Note: All examples below can be run directly in your browser using the testnet. Click the "Run" button to execute any example.

    + +
    + Test Identity: All examples use the testnet identity 5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk +
    This is a known identity with activity on testnet that you can use for testing. +
    +
    + +

    Queries

    +''' + + # Add query documentation + html_content += generate_operation_docs(query_defs, 'query', 'query') + + # Add state transition documentation + html_content += '

    State Transitions

    ' + html_content += generate_operation_docs(transition_defs, 'transition', 'transition') + + # Close main content div + html_content += ''' + ↑ Top +
    + + + + +''' + + return html_content + +def generate_ai_reference_md(query_defs, transition_defs): + """Generate AI-friendly markdown reference""" + + md_content = '''# Dash Platform WASM JS SDK - AI Reference + +## Overview +The Dash Platform WASM JS SDK provides WebAssembly bindings for interacting with Dash Platform from JavaScript/TypeScript. This reference is optimized for AI understanding and quick implementation. + +## Quick Setup +```javascript +// Import and initialize +import init, { WasmSdk } from './pkg/wasm_sdk.js'; + +await init(); +const transport = { + url: "https://52.12.176.90:1443/", // testnet + network: "testnet" +}; +const proofs = true; // Enable proof verification +const sdk = await WasmSdk.new(transport, proofs); +``` + +## Authentication +Most state transitions require authentication: +```javascript +const identityHex = "hex_encoded_identity"; +const privateKeyHex = "hex_encoded_private_key"; +``` + +## Query Operations + +### Pattern +All queries follow this pattern: +```javascript +const result = await sdk.{query_name}(param1, param2, ...); +``` + +### Available Queries +''' + + # Document all queries + for cat_key, category in query_defs.items(): + md_content += f"\n#### {category.get('label', cat_key)}\n" + + queries = category.get('queries', {}) + for query_key, query in queries.items(): + md_content += f"\n**{query.get('label', query_key)}** - `{query_key}`\n" + md_content += f"*{query.get('description', 'No description')}*\n\n" + + # Parameters + inputs = query.get('inputs', []) + if inputs: + md_content += "Parameters:\n" + for param in inputs: + req = "required" if param.get('required', False) else "optional" + md_content += f"- `{param.get('name', 'unknown')}` ({param.get('type', 'text')}, {req})" + + if param.get('label') and param.get('label') != param.get('name'): + md_content += f" - {param.get('label')}" + + if param.get('placeholder'): + md_content += f"\n - Example: `{param.get('placeholder')}`" + + if param.get('options'): + md_content += "\n - Options: " + opts = [f"`{opt.get('value')}` ({opt.get('label')})" for opt in param.get('options', [])] + md_content += ', '.join(opts) + + md_content += "\n" + else: + md_content += "No parameters required.\n" + + # Example + md_content += f"\nExample:\n```javascript\n" + + # Generate example based on query type + if query_key == 'getIdentity': + md_content += 'const identity = await sdk.getIdentity("GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec");' + elif query_key == 'getDocuments': + md_content += '''const docs = await sdk.getDocuments( + contractId, + "note", + JSON.stringify([["$ownerId", "==", identityId]]), + JSON.stringify([["$createdAt", "desc"]]), + 10 +);''' + elif query_key == 'getIdentityBalance': + md_content += 'const balance = await sdk.getIdentityBalance(identityId);' + elif query_key == 'getPathElements': + md_content += '''// Access any data in the Dash Platform state tree +// Common root paths: +// - DataContractDocuments: 64 +// - Identities: 32 +// - UniquePublicKeyHashesToIdentities: 24 +// - NonUniquePublicKeyKeyHashesToIdentities: 8 +// - Tokens: 16 +// - Pools: 48 +// - PreFundedSpecializedBalances: 40 +// - SpentAssetLockTransactions: 72 +// - WithdrawalTransactions: 80 +// - GroupActions: 88 +// - Balances: 96 +// - Misc: 104 +// - Votes: 112 +// - Versions: 120 + +// Example: Get identity balance +const result = await sdk.getPathElements(['96'], ['identityId']); + +// Example: Get identity info +const identityKeys = await sdk.getPathElements(['32'], ['identityId']); + +// Example: Get contract documents +const documents = await sdk.getPathElements(['64'], ['contractId', '1', 'documentType']);''' + else: + # Generic example + params = [] + for inp in inputs: + if inp.get('required', False): + if inp.get('type') == 'array': + params.append('[]') + elif inp.get('type') == 'number': + params.append('100') + else: + params.append(f'"{inp.get("name", "value")}"') + md_content += f'const result = await sdk.{query_key}({", ".join(params)});' + + md_content += "\n```\n" + + # Document state transitions + md_content += "\n## State Transition Operations\n\n### Pattern\n" + md_content += "All state transitions require authentication and follow this pattern:\n" + md_content += "```javascript\nconst result = await sdk.{transition_name}(identityHex, ...params, privateKeyHex);\n```\n" + + md_content += "\n### Available State Transitions\n" + + for cat_key, category in transition_defs.items(): + md_content += f"\n#### {category.get('label', cat_key)}\n" + + transitions = category.get('transitions', {}) + for trans_key, transition in transitions.items(): + md_content += f"\n**{transition.get('label', trans_key)}** - `{trans_key}`\n" + md_content += f"*{transition.get('description', 'No description')}*\n\n" + + # Parameters + inputs = transition.get('inputs', []) + if inputs: + md_content += "Parameters (in addition to identity/key):\n" + for param in inputs: + req = "required" if param.get('required', False) else "optional" + md_content += f"- `{param.get('name', 'unknown')}` ({param.get('type', 'text')}, {req})" + + if param.get('label') and param.get('label') != param.get('name'): + md_content += f" - {param.get('label')}" + + if param.get('placeholder'): + md_content += f"\n - Example: `{param.get('placeholder')}`" + + md_content += "\n" + + # Example + md_content += f"\nExample:\n```javascript\n" + + # Generate specific examples + if trans_key == 'documentCreate': + md_content += '''const result = await sdk.document_create( + identityHex, + contractId, + "note", + JSON.stringify({ message: "Hello!" }), + privateKeyHex +);''' + elif trans_key == 'tokenTransfer': + md_content += '''const result = await sdk.token_transfer( + identityHex, + contractId, + tokenId, + 1000000, // amount + recipientId, + privateKeyHex +);''' + else: + md_content += f'const result = await sdk.{trans_key}(identityHex, /* params */, privateKeyHex);' + + md_content += "\n```\n" + + # Add common patterns section + md_content += ''' +## Common Patterns + +### Error Handling +```javascript +try { + const result = await sdk.getIdentity(identityId); + console.log(result); +} catch (error) { + console.error("Query failed:", error); +} +``` + +### Working with Proofs +```javascript +// Enable proofs during SDK initialization +const sdk = await WasmSdk.new(transport, true); + +// Query with proof verification +const identityWithProof = await sdk.getIdentity(identityId); +``` + +### Document Queries with Where/OrderBy +```javascript +// Where clause format: [[field, operator, value], ...] +const whereClause = JSON.stringify([ + ["$ownerId", "==", identityId], + ["age", ">=", 18] +]); + +// OrderBy format: [[field, direction], ...] +const orderBy = JSON.stringify([ + ["$createdAt", "desc"] +]); + +const docs = await sdk.getDocuments( + contractId, + documentType, + whereClause, + orderBy, + limit +); +``` + +### Batch Operations +```javascript +// Get multiple identities +const identityIds = ["id1", "id2", "id3"]; +const balances = await sdk.getIdentitiesBalances(identityIds); +``` + +## Important Notes + +1. **Network Endpoints**: + - Testnet: `https://52.12.176.90:1443/` + - Mainnet: Update when available + +2. **Identity Format**: Identity IDs and keys should be hex-encoded strings + +3. **Credits**: All fees are paid in credits (1 credit = 1 satoshi equivalent) + +4. **Nonces**: The SDK automatically handles nonce management for state transitions + +5. **Proofs**: Enable proofs for production applications to ensure data integrity + +## Troubleshooting + +- **Connection errors**: Verify network endpoint and that SDK is initialized +- **Invalid parameters**: Check parameter types and required fields +- **Authentication failures**: Ensure correct identity/key format and key permissions +- **Query errors**: Validate contract IDs, document types, and field names exist +''' + + return md_content + +def main(): + """Main function to generate documentation""" + + # Get paths + script_dir = Path(__file__).parent + index_file = script_dir / 'index.html' + + if not index_file.exists(): + print(f"Error: index.html not found at {index_file}") + return 1 + + # First check if we have manually fixed definitions + fixed_file = script_dir / 'fixed_definitions.json' + extracted_file = script_dir / 'extracted_definitions.json' + + if fixed_file.exists(): + print("Using manually fixed definitions...") + definitions_file = fixed_file + else: + # Extract definitions using the extraction script + print("Extracting definitions from index.html...") + import subprocess + result = subprocess.run(['python3', 'extract_definitions.py'], cwd=script_dir, capture_output=True, text=True) + if result.returncode != 0: + print(f"Error extracting definitions: {result.stderr}") + return 1 + + if not extracted_file.exists(): + print("Error: Could not find extracted definitions") + return 1 + definitions_file = extracted_file + + with open(definitions_file, 'r') as f: + extracted = json.load(f) + + query_defs = extracted.get('queries', {}) + transition_defs = extracted.get('transitions', {}) + + # Clean up the extracted data (remove invalid entries like 'dependsOn') + for cat_key, category in list(query_defs.items()): + queries = category.get('queries', {}) + for q_key in list(queries.keys()): + if q_key in ['dependsOn', 'offset', 'limit'] or not queries[q_key].get('label'): + del queries[q_key] + + for cat_key, category in list(transition_defs.items()): + transitions = category.get('transitions', {}) + for t_key in list(transitions.keys()): + if t_key in ['dependsOn'] or not transitions[t_key].get('label'): + del transitions[t_key] + + print(f"Found {sum(len(cat.get('queries', {})) for cat in query_defs.values())} queries") + print(f"Found {sum(len(cat.get('transitions', {})) for cat in transition_defs.values())} state transitions") + + # Generate user docs + print("\nGenerating user documentation (docs.html)...") + user_docs_html = generate_user_docs_html(query_defs, transition_defs) + docs_file = script_dir / 'docs.html' + with open(docs_file, 'w', encoding='utf-8') as f: + f.write(user_docs_html) + print(f"Written to {docs_file}") + + # Generate AI reference + print("\nGenerating AI reference (AI_REFERENCE.md)...") + ai_reference_md = generate_ai_reference_md(query_defs, transition_defs) + ai_ref_file = script_dir / 'AI_REFERENCE.md' + with open(ai_ref_file, 'w', encoding='utf-8') as f: + f.write(ai_reference_md) + print(f"Written to {ai_ref_file}") + + # Generate documentation manifest for CI checks + manifest = { + "generated_at": datetime.now().isoformat(), + "queries": {}, + "transitions": {} + } + + for cat_key, category in query_defs.items(): + for query_key in category.get('queries', {}).keys(): + manifest["queries"][query_key] = { + "category": cat_key, + "documented": True + } + + for cat_key, category in transition_defs.items(): + for trans_key in category.get('transitions', {}).keys(): + manifest["transitions"][trans_key] = { + "category": cat_key, + "documented": True + } + + manifest_file = script_dir / 'docs_manifest.json' + with open(manifest_file, 'w', encoding='utf-8') as f: + json.dump(manifest, f, indent=2) + print(f"\nGenerated documentation manifest at {manifest_file}") + + print("\nDocumentation generation complete!") + return 0 + +if __name__ == "__main__": + exit(main()) \ No newline at end of file diff --git a/packages/wasm-sdk/index.html b/packages/wasm-sdk/index.html index 61adc5181d4..1996061fe50 100644 --- a/packages/wasm-sdk/index.html +++ b/packages/wasm-sdk/index.html @@ -7,6 +7,9 @@ + Dash Platform WASM JS SDK + + + + +

    Check Identity Keys

    + +
    + + +
    + +
    + + +
    + + + + +
    + + + + \ No newline at end of file diff --git a/packages/wasm-sdk/tests/check_posts.html b/packages/wasm-sdk/tests/check_posts.html new file mode 100644 index 00000000000..ecd9d965e0b --- /dev/null +++ b/packages/wasm-sdk/tests/check_posts.html @@ -0,0 +1,107 @@ + + + + + Check Posts + + + +

    Check Your Posts

    + +

    Identity ID: 5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk

    +

    Contract ID: 9nzpvjVSStUrhkEs3eNHw2JYpcNoLh1MjmqW45QiyjSa

    + + + +
    + + + + \ No newline at end of file diff --git a/packages/wasm-sdk/tests/derive_public_key.html b/packages/wasm-sdk/tests/derive_public_key.html new file mode 100644 index 00000000000..288789c24ea --- /dev/null +++ b/packages/wasm-sdk/tests/derive_public_key.html @@ -0,0 +1,114 @@ + + + + + Derive Public Key + + + + +

    Derive Public Key from Private Key

    + +
    + + +
    + + + +
    + + + + \ No newline at end of file diff --git a/packages/wasm-sdk/tests/test-cache.html b/packages/wasm-sdk/tests/test-cache.html new file mode 100644 index 00000000000..8bf04b686e8 --- /dev/null +++ b/packages/wasm-sdk/tests/test-cache.html @@ -0,0 +1,150 @@ + + + + Cache Test + + + +

    WASM SDK Cache Test

    + +
    Checking service worker...
    + +
    + + + + +
    + +
    + + + + \ No newline at end of file diff --git a/packages/wasm-sdk/tests/test_group_queries.html b/packages/wasm-sdk/tests/test_group_queries.html new file mode 100644 index 00000000000..3ffe4a94de1 --- /dev/null +++ b/packages/wasm-sdk/tests/test_group_queries.html @@ -0,0 +1,81 @@ + + + + Test Group Queries + + +

    Group Query Tests

    +
    + + + + \ No newline at end of file diff --git a/packages/wasm-sdk/tests/test_groups.html b/packages/wasm-sdk/tests/test_groups.html new file mode 100644 index 00000000000..a3694fccfb3 --- /dev/null +++ b/packages/wasm-sdk/tests/test_groups.html @@ -0,0 +1,101 @@ + + + + Test Group Queries + + +

    Test Group Queries

    + +
    
    +
    +    
    +
    +
    \ No newline at end of file
    diff --git a/packages/wasm-sdk/tests/test_nonce.html b/packages/wasm-sdk/tests/test_nonce.html
    new file mode 100644
    index 00000000000..fdcd377b868
    --- /dev/null
    +++ b/packages/wasm-sdk/tests/test_nonce.html
    @@ -0,0 +1,55 @@
    +
    +
    +
    +    
    +    Test Identity Nonce
    +
    +
    +    

    Identity Nonce Test

    +
    
    +    
    +    
    +
    +
    \ No newline at end of file
    diff --git a/packages/wasm-sdk/tests/test_post_create.html b/packages/wasm-sdk/tests/test_post_create.html
    new file mode 100644
    index 00000000000..fc60a19d611
    --- /dev/null
    +++ b/packages/wasm-sdk/tests/test_post_create.html
    @@ -0,0 +1,165 @@
    +
    +
    +
    +    
    +    Test Post Creation
    +    
    +
    +
    +    

    Test Post Creation

    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + + + +
    + + + + \ No newline at end of file diff --git a/packages/wasm-sdk/tests/test_proof.html b/packages/wasm-sdk/tests/test_proof.html new file mode 100644 index 00000000000..68aeff775a3 --- /dev/null +++ b/packages/wasm-sdk/tests/test_proof.html @@ -0,0 +1,156 @@ + + + + Test Proof Toggle + + + +

    WASM SDK Proof Functions Test

    + +
    + + + + \ No newline at end of file diff --git a/packages/wasm-sdk/tests/test_proof.js b/packages/wasm-sdk/tests/test_proof.js new file mode 100644 index 00000000000..244f85b68d4 --- /dev/null +++ b/packages/wasm-sdk/tests/test_proof.js @@ -0,0 +1,57 @@ +import { readFileSync, existsSync } from 'fs'; +import { WASI } from 'wasi'; +import { argv, env } from 'process'; +import { join } from 'path'; + +// Create WASI instance +const wasi = new WASI({ + args: argv, + env, + preopens: {} +}); + +// Read and instantiate WASM module +let wasmBuffer, wasmModule, instance; + +// Check if WASM file exists before attempting to read it +const wasmPath = './pkg/wasm_sdk_bg.wasm'; +if (!existsSync(wasmPath)) { + console.error('Error: WASM file not found at:', wasmPath); + console.error('Please build the WASM module first by running: ./build.sh'); + process.exit(1); +} + +try { + wasmBuffer = readFileSync(wasmPath); + console.log('WASM file read successfully'); +} catch (error) { + console.error('Failed to read WASM file:', error.message); + console.error('Make sure you have built the WASM module with: ./build.sh'); + process.exit(1); +} + +try { + wasmModule = new WebAssembly.Module(wasmBuffer); + console.log('WASM module created successfully'); +} catch (error) { + console.error('Failed to create WebAssembly module:', error.message); + console.error('The WASM file may be corrupted. Try rebuilding with: ./build.sh'); + process.exit(1); +} + +try { + instance = new WebAssembly.Instance(wasmModule, { + wasi_snapshot_preview1: wasi.wasiImport + }); + console.log('WASM instance created successfully'); +} catch (error) { + console.error('Failed to instantiate WebAssembly module:', error.message); + console.error('There may be import/export mismatches or runtime issues'); + process.exit(1); +} + +// Initialize WASI +wasi.initialize(instance); + +console.log('WASM module loaded successfully!'); +console.log('Available exports:', Object.keys(instance.exports)); \ No newline at end of file diff --git a/packages/wasm-sdk/tests/test_proof_result.html b/packages/wasm-sdk/tests/test_proof_result.html new file mode 100644 index 00000000000..f0695156793 --- /dev/null +++ b/packages/wasm-sdk/tests/test_proof_result.html @@ -0,0 +1,59 @@ + + + + + Test Proof Result + + +

    Proof Result Test

    +
    
    +    
    +    
    +
    +
    \ No newline at end of file
    diff --git a/packages/wasm-sdk/tests/test_proof_split.html b/packages/wasm-sdk/tests/test_proof_split.html
    new file mode 100644
    index 00000000000..f4884214a48
    --- /dev/null
    +++ b/packages/wasm-sdk/tests/test_proof_split.html
    @@ -0,0 +1,144 @@
    +
    +
    +
    +    Test Proof Split View
    +    
    +
    +
    +    

    Test Proof Split View

    + +
    +

    Mock Proof Response Display

    +

    This shows how a proof response should be displayed with the split view:

    + +
    +
    +
    Data
    +
    +
    {
    +  "id": "4EfA9Jrvv3nnCFdSf7fad59851iiTRZ6Wcu6YVJ4iSeF",
    +  "balance": "1000000000",
    +  "publicKeys": [
    +    {
    +      "id": 0,
    +      "purpose": 0,
    +      "securityLevel": 0,
    +      "keyType": 0,
    +      "data": "AkVZTLXFDp3H8QVQV6p+XJpTXEJxDHSpP16hbWFqUt7g"
    +    }
    +  ],
    +  "revision": 0
    +}
    +
    +
    +
    +
    Proof & Metadata
    +
    +
    {
    +  "metadata": {
    +    "height": 12456,
    +    "coreChainLockedHeight": 987654,
    +    "epoch": 1234,
    +    "timeMs": 1738594800000,
    +    "protocolVersion": 1,
    +    "chainId": "dash-testnet-44"
    +  },
    +  "proof": {
    +    "grovedbProof": "0x0123456789abcdef...",
    +    "quorumHash": "0xfedcba9876543210...",
    +    "signature": "0xabcdef0123456789...",
    +    "round": 1,
    +    "blockIdHash": "0x1234567890abcdef...",
    +    "quorumType": 6
    +  }
    +}
    +
    +
    +
    +
    + +
    +

    Expected Behavior

    + +
    + + \ No newline at end of file diff --git a/packages/wasm-sdk/tests/test_serialization.html b/packages/wasm-sdk/tests/test_serialization.html new file mode 100644 index 00000000000..e54599e9d5c --- /dev/null +++ b/packages/wasm-sdk/tests/test_serialization.html @@ -0,0 +1,103 @@ + + + + + Test Serialization + + + +

    Test Serialization

    + + + + + +
    + + + + \ No newline at end of file diff --git a/packages/wasm-sdk/tests/verify_proof_display.html b/packages/wasm-sdk/tests/verify_proof_display.html new file mode 100644 index 00000000000..e8bc258c629 --- /dev/null +++ b/packages/wasm-sdk/tests/verify_proof_display.html @@ -0,0 +1,87 @@ + + + + Verify Proof Display + + + +
    +

    ✅ Proof Display Implementation Complete

    + +

    What's been implemented:

    + + +

    How to test:

    +
      +
    1. Open http://localhost:8888
    2. +
    3. Enable the Proof toggle at the top of the page
    4. +
    5. Select Identity Queries → Get Identity Nonce
    6. +
    7. Enter an identity ID (e.g., 5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk)
    8. +
    9. Click Execute Query
    10. +
    + +

    Expected result with Proof toggle ON:

    + + +

    Other queries with proof support:

    + +
    + + \ No newline at end of file