diff --git a/.github/workflows/ci-server-reusable.yml b/.github/workflows/ci-server-reusable.yml
new file mode 100644
index 0000000..10ba3c6
--- /dev/null
+++ b/.github/workflows/ci-server-reusable.yml
@@ -0,0 +1,159 @@
+name: Server CI Reusable
+
+on:
+ workflow_call:
+ inputs:
+ job_name:
+ required: true
+ type: string
+ build_script:
+ required: true
+ type: string
+ test_script:
+ required: true
+ type: string
+ test_working_directory:
+ required: true
+ type: string
+ run_integration_tests:
+ required: false
+ default: false
+ type: boolean
+ integration_test_script:
+ required: false
+ default: ""
+ type: string
+ integration_test_working_directory:
+ required: false
+ default: ""
+ type: string
+ dockerfile:
+ required: true
+ type: string
+ image_ref:
+ required: true
+ type: string
+ trivy_results_file:
+ required: true
+ type: string
+ trivy_sarif_file:
+ required: true
+ type: string
+ trivy_scan_label:
+ required: true
+ type: string
+ sarif_category:
+ required: true
+ type: string
+
+jobs:
+ server:
+ name: ${{ inputs.job_name }}
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Use Node.js 22.x
+ uses: actions/setup-node@v4
+ with:
+ node-version: 22.x
+ cache: npm
+ cache-dependency-path: package-lock.json
+
+ - name: Install dependencies (monorepo)
+ run: npm ci --workspaces
+
+ - name: Build shared package
+ run: npm run build:shared
+
+ - name: Build target server
+ run: ${{ inputs.build_script }}
+
+ - name: Run tests
+ run: ${{ inputs.test_script }}
+ working-directory: ${{ inputs.test_working_directory }}
+
+ - name: Run integration tests
+ if: inputs.run_integration_tests
+ run: ${{ inputs.integration_test_script }}
+ working-directory: ${{ inputs.integration_test_working_directory }}
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Build image for scanning
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: ${{ inputs.dockerfile }}
+ load: true
+ tags: ${{ inputs.image_ref }}
+ build-args: |
+ BUILD_NUMBER=${{ github.run_number }}
+
+ - name: Scan image for HIGH and CRITICAL vulnerabilities
+ id: trivy_scan
+ continue-on-error: true
+ uses: aquasecurity/trivy-action@v0.35.0
+ with:
+ image-ref: ${{ inputs.image_ref }}
+ format: table
+ output: ${{ inputs.trivy_results_file }}
+ ignore-unfixed: true
+ severity: HIGH,CRITICAL
+ exit-code: '1'
+
+ - name: Add Trivy report to job summary
+ if: always()
+ run: |
+ {
+ echo "## ${{ inputs.trivy_scan_label }}"
+ echo
+ if [ "${{ steps.trivy_scan.outcome }}" = "failure" ]; then
+ echo "**Status:** FAILED (HIGH/CRITICAL vulnerabilities found)"
+ else
+ echo "**Status:** PASSED (no HIGH/CRITICAL vulnerabilities found)"
+ fi
+ echo
+ echo "Full Trivy output
"
+ echo
+ echo '```text'
+ cat "${{ inputs.trivy_results_file }}"
+ echo '```'
+ echo " "
+ } >> "$GITHUB_STEP_SUMMARY"
+
+ - name: Generate Trivy SARIF report
+ if: always()
+ uses: aquasecurity/trivy-action@v0.35.0
+ with:
+ image-ref: ${{ inputs.image_ref }}
+ format: sarif
+ output: ${{ inputs.trivy_sarif_file }}
+ ignore-unfixed: true
+ severity: HIGH,CRITICAL
+ exit-code: '0'
+
+ - name: Upload Trivy SARIF to GitHub Security
+ id: trivy_sarif_upload
+ continue-on-error: true
+ if: always()
+ uses: github/codeql-action/upload-sarif@v4
+ with:
+ sarif_file: ${{ inputs.trivy_sarif_file }}
+ category: ${{ inputs.sarif_category }}
+
+ - name: Add SARIF upload status to job summary
+ if: always() && steps.trivy_sarif_upload.outcome == 'failure'
+ run: |
+ echo >> "$GITHUB_STEP_SUMMARY"
+ echo "## SARIF Upload" >> "$GITHUB_STEP_SUMMARY"
+ echo >> "$GITHUB_STEP_SUMMARY"
+ echo "SARIF upload was skipped or failed. GitHub code scanning may not be enabled for this repository." >> "$GITHUB_STEP_SUMMARY"
+
+ - name: Fail job if Trivy found HIGH/CRITICAL issues
+ if: steps.trivy_scan.outcome == 'failure'
+ run: |
+ echo "Trivy detected HIGH/CRITICAL vulnerabilities. See job summary and Security tab for details."
+ exit 1
diff --git a/.github/workflows/ci-shared.yml b/.github/workflows/ci-shared.yml
new file mode 100644
index 0000000..f94585f
--- /dev/null
+++ b/.github/workflows/ci-shared.yml
@@ -0,0 +1,44 @@
+name: Shared Package CI
+
+on:
+ pull_request:
+ paths:
+ - 'packages/mcp-shared/**'
+ - 'package.json'
+ - 'package-lock.json'
+ - '.github/workflows/ci-shared.yml'
+ push:
+ branches:
+ - master
+ paths:
+ - 'packages/mcp-shared/**'
+ - 'package.json'
+ - 'package-lock.json'
+ - '.github/workflows/ci-shared.yml'
+
+jobs:
+ shared:
+ name: Build and Test mcp-shared
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Use Node.js 22.x
+ uses: actions/setup-node@v4
+ with:
+ node-version: 22.x
+ cache: npm
+ cache-dependency-path: package-lock.json
+
+ - name: Install dependencies (monorepo)
+ run: npm ci --workspaces
+
+ - name: Build shared package
+ run: npm run build:shared
+
+ - name: Run tests (mcp-shared)
+ run: npm run test -- --run
+ working-directory: packages/mcp-shared
diff --git a/.github/workflows/ci-wallet.yml b/.github/workflows/ci-wallet.yml
new file mode 100644
index 0000000..0913001
--- /dev/null
+++ b/.github/workflows/ci-wallet.yml
@@ -0,0 +1,45 @@
+name: Wallet CI
+
+on:
+ pull_request:
+ paths:
+ - 'apps/wallet-server/**'
+ - 'packages/mcp-shared/**'
+ - 'package.json'
+ - 'package-lock.json'
+ - 'scripts/**'
+ - '.github/workflows/ci-wallet.yml'
+ - '.github/workflows/ci-server-reusable.yml'
+ push:
+ branches:
+ - master
+ paths:
+ - 'apps/wallet-server/**'
+ - 'packages/mcp-shared/**'
+ - 'package.json'
+ - 'package-lock.json'
+ - 'scripts/**'
+ - '.github/workflows/ci-wallet.yml'
+ - '.github/workflows/ci-server-reusable.yml'
+
+jobs:
+ wallet:
+ uses: ./.github/workflows/ci-server-reusable.yml
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+ with:
+ job_name: Build and Test Wallet Server
+ build_script: npm run build:wallet
+ test_script: npm test
+ test_working_directory: apps/wallet-server
+ run_integration_tests: true
+ integration_test_script: npm run test:integration
+ integration_test_working_directory: apps/wallet-server
+ dockerfile: ./apps/wallet-server/Dockerfile
+ image_ref: truvera-wallet-mcp:ci
+ trivy_results_file: wallet-trivy-results.txt
+ trivy_sarif_file: wallet-trivy-results.sarif
+ trivy_scan_label: Wallet Trivy Image Scan
+ sarif_category: trivy-container-scan-wallet
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 61c5ef4..bb4866e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,130 +1,46 @@
-name: CI
+name: API CI
on:
pull_request:
+ paths:
+ - 'apps/truvera-api/**'
+ - 'packages/mcp-shared/**'
+ - 'package.json'
+ - 'package-lock.json'
+ - 'scripts/**'
+ - '.github/workflows/ci.yml'
+ - '.github/workflows/ci-server-reusable.yml'
push:
branches:
- master
-
+ paths:
+ - 'apps/truvera-api/**'
+ - 'packages/mcp-shared/**'
+ - 'package.json'
+ - 'package-lock.json'
+ - 'scripts/**'
+ - '.github/workflows/ci.yml'
+ - '.github/workflows/ci-server-reusable.yml'
+
jobs:
- build:
- name: Build and Test
- runs-on: ubuntu-latest
+ api:
+ uses: ./.github/workflows/ci-server-reusable.yml
permissions:
actions: read
contents: read
security-events: write
- strategy:
- matrix:
- node-version: [22.x]
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ matrix.node-version }}
- cache: 'npm'
- cache-dependency-path: 'package-lock.json'
-
- - name: Install dependencies (monorepo)
- run: npm ci --workspaces
-
- - name: Build shared package
- run: npm run build:shared
-
- - name: Build truvera-api
- run: npm run build:api
-
- - name: Build wallet-server
- run: npm run build --workspace=apps/wallet-server
-
- - name: Run tests (truvera-api)
- run: npm run test -- --run
- working-directory: apps/truvera-api
-
- - name: Run tests (mcp-shared)
- run: npm run test -- --run
- working-directory: packages/mcp-shared
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Build truvera-api image for scanning
- uses: docker/build-push-action@v6
- with:
- context: .
- file: ./apps/truvera-api/Dockerfile
- load: true
- tags: truvera-api-mcp:ci
- build-args: |
- BUILD_NUMBER=${{ github.run_number }}
-
- - name: Scan truvera-api image for HIGH and CRITICAL vulnerabilities
- id: trivy_scan
- continue-on-error: true
- uses: aquasecurity/trivy-action@v0.35.0
- with:
- image-ref: truvera-api-mcp:ci
- format: table
- output: trivy-results.txt
- ignore-unfixed: true
- severity: HIGH,CRITICAL
- exit-code: '1'
-
- - name: Add Trivy report to job summary
- if: always()
- run: |
- {
- echo "## Trivy Image Scan"
- echo
- if [ "${{ steps.trivy_scan.outcome }}" = "failure" ]; then
- echo "**Status:** FAILED (HIGH/CRITICAL vulnerabilities found)"
- else
- echo "**Status:** PASSED (no HIGH/CRITICAL vulnerabilities found)"
- fi
- echo
- echo "Full Trivy output
"
- echo
- echo '```text'
- cat trivy-results.txt
- echo '```'
- echo " "
- } >> "$GITHUB_STEP_SUMMARY"
-
- - name: Generate Trivy SARIF report
- if: always()
- uses: aquasecurity/trivy-action@v0.35.0
- with:
- image-ref: truvera-api-mcp:ci
- format: sarif
- output: trivy-results.sarif
- ignore-unfixed: true
- severity: HIGH,CRITICAL
- exit-code: '0'
-
- - name: Upload Trivy SARIF to GitHub Security
- id: trivy_sarif_upload
- continue-on-error: true
- if: always()
- uses: github/codeql-action/upload-sarif@v4
- with:
- sarif_file: trivy-results.sarif
- category: trivy-container-scan
-
- - name: Add SARIF upload status to job summary
- if: always()
- run: |
- if [ "${{ steps.trivy_sarif_upload.outcome }}" = "failure" ]; then
- echo >> "$GITHUB_STEP_SUMMARY"
- echo "## SARIF Upload" >> "$GITHUB_STEP_SUMMARY"
- echo >> "$GITHUB_STEP_SUMMARY"
- echo "SARIF upload was skipped or failed. GitHub code scanning may not be enabled for this repository." >> "$GITHUB_STEP_SUMMARY"
- fi
+ with:
+ job_name: Build and Test API Server
+ build_script: npm run build:api
+ test_script: npm run test -- --run
+ test_working_directory: apps/truvera-api
+ run_integration_tests: false
+ integration_test_script: ""
+ integration_test_working_directory: ""
+ dockerfile: ./apps/truvera-api/Dockerfile
+ image_ref: truvera-api-mcp:ci
+ trivy_results_file: trivy-results.txt
+ trivy_sarif_file: trivy-results.sarif
+ trivy_scan_label: API Trivy Image Scan
+ sarif_category: trivy-container-scan-api
- - name: Fail job if Trivy found HIGH/CRITICAL issues
- if: steps.trivy_scan.outcome == 'failure'
- run: |
- echo "Trivy detected HIGH/CRITICAL vulnerabilities. See job summary and Security tab for details."
- exit 1
diff --git a/.github/workflows/docker-publish-reusable.yml b/.github/workflows/docker-publish-reusable.yml
new file mode 100644
index 0000000..2f25dea
--- /dev/null
+++ b/.github/workflows/docker-publish-reusable.yml
@@ -0,0 +1,90 @@
+name: Docker Publish Reusable
+
+on:
+ workflow_call:
+ inputs:
+ docker_image:
+ required: true
+ type: string
+ dockerfile:
+ required: true
+ type: string
+ build_number_file:
+ required: true
+ type: string
+ should_push:
+ required: true
+ type: boolean
+
+jobs:
+ publish:
+ name: Build and Publish Image
+ runs-on: ubuntu-latest
+ env:
+ DOCKER_IMAGE: ${{ inputs.docker_image }}
+ DOCKERFILE: ${{ inputs.dockerfile }}
+ BUILD_NUMBER_FILE: ${{ inputs.build_number_file }}
+ SHOULD_PUSH: ${{ inputs.should_push }}
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Read build number
+ id: build_number
+ run: |
+ if [ -f "${BUILD_NUMBER_FILE}" ]; then
+ BUILD_NUM=$(cat "${BUILD_NUMBER_FILE}")
+ echo "Using ${BUILD_NUMBER_FILE}"
+ else
+ BUILD_NUM="${{ github.run_number }}"
+ echo "${BUILD_NUMBER_FILE} not found; using GitHub run number"
+ fi
+ echo "build_number=$BUILD_NUM" >> "$GITHUB_OUTPUT"
+ echo "Build number: $BUILD_NUM"
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Log in to DockerHub
+ if: ${{ env.SHOULD_PUSH == 'true' }}
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKER_HUB_USERNAME }}
+ password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
+
+ - name: Extract metadata for Docker
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: |
+ ${{ env.DOCKER_IMAGE }}
+ tags: |
+ type=raw,value=latest,enable=${{ github.event_name == 'release' && github.event.release.target_commitish == github.event.repository.default_branch }}
+ type=raw,value=${{ steps.build_number.outputs.build_number }}
+ labels: |
+ org.opencontainers.image.licenses=LicenseRef-DL-NPL
+
+ - name: Build and publish Docker image
+ id: docker_build
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: ${{ env.DOCKERFILE }}
+ push: ${{ env.SHOULD_PUSH == 'true' }}
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ sbom: ${{ env.SHOULD_PUSH == 'true' }}
+ provenance: ${{ env.SHOULD_PUSH == 'true' }}
+ build-args: |
+ BUILD_NUMBER=${{ steps.build_number.outputs.build_number }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+ platforms: linux/amd64,linux/arm64
+
+ - name: Image digest
+ if: ${{ env.SHOULD_PUSH == 'true' }}
+ run: echo "Image pushed with digest ${{ steps.docker_build.outputs.digest }}"
+
+ - name: Image build only
+ if: ${{ env.SHOULD_PUSH != 'true' }}
+ run: echo "Image built without push because workflow_dispatch input 'push' was false"
diff --git a/.github/workflows/docker-publish-wallet.yml b/.github/workflows/docker-publish-wallet.yml
new file mode 100644
index 0000000..13e14ea
--- /dev/null
+++ b/.github/workflows/docker-publish-wallet.yml
@@ -0,0 +1,36 @@
+name: Publish Wallet Docker Image
+
+on:
+ push:
+ branches:
+ - master
+ paths:
+ - 'apps/wallet-server/**'
+ - 'packages/mcp-shared/**'
+ - 'package.json'
+ - 'package-lock.json'
+ - 'scripts/**'
+ - '.github/workflows/docker-publish-wallet.yml'
+ - '.github/workflows/docker-publish-reusable.yml'
+ release:
+ types: [published]
+ workflow_dispatch:
+ inputs:
+ push:
+ description: Push image to DockerHub
+ required: false
+ default: true
+ type: boolean
+
+jobs:
+ wallet:
+ uses: ./.github/workflows/docker-publish-reusable.yml
+ permissions:
+ contents: read
+ packages: write
+ id-token: write
+ with:
+ docker_image: docknetwork/truvera-wallet-mcp
+ dockerfile: ./apps/wallet-server/Dockerfile
+ build_number_file: apps/wallet-server/.buildnumber
+ should_push: ${{ github.event_name != 'workflow_dispatch' || inputs.push }}
diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml
index 54dfb2d..e261211 100644
--- a/.github/workflows/docker-publish.yml
+++ b/.github/workflows/docker-publish.yml
@@ -1,4 +1,4 @@
-name: Build and Push Docker Images
+name: Publish API Docker Image
on:
push:
@@ -7,91 +7,30 @@ on:
paths:
- 'apps/truvera-api/**'
- 'packages/mcp-shared/**'
+ - 'package.json'
+ - 'package-lock.json'
+ - 'scripts/**'
- '.github/workflows/docker-publish.yml'
-
+ - '.github/workflows/docker-publish-reusable.yml'
release:
types: [published]
-
workflow_dispatch:
inputs:
push:
- description: 'Push images to DockerHub'
+ description: Push image to DockerHub
required: false
default: true
type: boolean
jobs:
- build-and-push:
- name: Build and Push truvera-api-mcp
- runs-on: ubuntu-latest
- env:
- SHOULD_PUSH: ${{ github.event_name != 'workflow_dispatch' || inputs.push }}
- DOCKER_IMAGE: docknetwork/truvera-api-mcp
+ api:
+ uses: ./.github/workflows/docker-publish-reusable.yml
permissions:
contents: read
packages: write
id-token: write
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- - name: Read build number
- id: build_number
- run: |
- if [ -f apps/truvera-api/.buildnumber ]; then
- BUILD_NUM=$(cat apps/truvera-api/.buildnumber)
- echo "Using apps/truvera-api/.buildnumber"
- else
- BUILD_NUM="${{ github.run_number }}"
- echo "apps/truvera-api/.buildnumber not found; using GitHub run number"
- fi
- echo "build_number=$BUILD_NUM" >> $GITHUB_OUTPUT
- echo "Build number: $BUILD_NUM"
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Log in to DockerHub
- if: ${{ env.SHOULD_PUSH == 'true' }}
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKER_HUB_USERNAME }}
- password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
-
- - name: Extract metadata for Docker
- id: meta
- uses: docker/metadata-action@v5
- with:
- images: |
- ${{ env.DOCKER_IMAGE }}
- tags: |
- type=raw,value=latest,enable=${{ github.event_name == 'release' && github.event.release.target_commitish == github.event.repository.default_branch }}
- type=raw,value=${{ steps.build_number.outputs.build_number }}
- labels: |
- org.opencontainers.image.licenses=LicenseRef-DL-NPL
-
- - name: Build and push API Docker image
- id: docker_build
- uses: docker/build-push-action@v6
- with:
- context: .
- file: ./apps/truvera-api/Dockerfile
- push: ${{ env.SHOULD_PUSH == 'true' }}
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
- sbom: ${{ env.SHOULD_PUSH == 'true' }}
- provenance: ${{ env.SHOULD_PUSH == 'true' }}
- build-args: |
- BUILD_NUMBER=${{ steps.build_number.outputs.build_number }}
- cache-from: type=gha
- cache-to: type=gha,mode=max
- platforms: linux/amd64,linux/arm64
-
- - name: Image digest
- if: ${{ env.SHOULD_PUSH == 'true' }}
- run: echo "Image pushed with digest ${{ steps.docker_build.outputs.digest }}"
-
- - name: Image build only
- if: ${{ env.SHOULD_PUSH != 'true' }}
- run: echo "Image built without push because workflow_dispatch input 'push' was false"
+ with:
+ docker_image: docknetwork/truvera-api-mcp
+ dockerfile: ./apps/truvera-api/Dockerfile
+ build_number_file: apps/truvera-api/.buildnumber
+ should_push: ${{ github.event_name != 'workflow_dispatch' || inputs.push }}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index c74bf16..0dde2a8 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -25,6 +25,27 @@
},
"isBackground": true,
"problemMatcher": []
+ },
+ {
+ "label": "build:wallet",
+ "type": "shell",
+ "command": "npm",
+ "args": ["run", "build"],
+ "options": {
+ "cwd": "${workspaceFolder}/apps/wallet-server"
+ },
+ "problemMatcher": ["$tsc"]
+ },
+ {
+ "label": "dev:wallet",
+ "type": "shell",
+ "command": "npm",
+ "args": ["run", "dev"],
+ "options": {
+ "cwd": "${workspaceFolder}/apps/wallet-server"
+ },
+ "isBackground": true,
+ "problemMatcher": []
}
]
}
diff --git a/WALLET_MCP_PLAN.md b/WALLET_MCP_PLAN.md
index e87deea..2b1499f 100644
--- a/WALLET_MCP_PLAN.md
+++ b/WALLET_MCP_PLAN.md
@@ -601,3 +601,7 @@ Proceeding with fast, iterative implementation in this order:
4. Phase 3.6: Credential client (4-5 hours)
5. Phase 3.7: Message client (3-4 hours)
6. Testing & iteration
+
+
+TODO:
+* Persistent wallet storage - currently only in memory so is wiped whenever you restart the server
\ No newline at end of file
diff --git a/apps/truvera-api/Dockerfile b/apps/truvera-api/Dockerfile
index 83909f9..1bdbfb4 100644
--- a/apps/truvera-api/Dockerfile
+++ b/apps/truvera-api/Dockerfile
@@ -13,6 +13,7 @@ RUN apk update && apk upgrade --no-cache && \
# Copy root package files for workspace
COPY package*.json ./
+COPY scripts ./scripts
# Copy workspace package.json files first (for Docker layer caching)
COPY packages/mcp-shared/package*.json ./packages/mcp-shared/
@@ -46,6 +47,7 @@ RUN apk update && apk upgrade --no-cache && \
# Copy root package files
COPY package*.json ./
+COPY scripts ./scripts
# Include repository license in the published runtime image
COPY LICENSE /licenses/LICENSE
diff --git a/apps/truvera-api/src/build-info.ts b/apps/truvera-api/src/build-info.ts
index 72653a0..b21b7bd 100644
--- a/apps/truvera-api/src/build-info.ts
+++ b/apps/truvera-api/src/build-info.ts
@@ -1,6 +1,6 @@
// Auto-generated build information
export const BUILD_INFO = {
- timestamp: '2026-04-02T20:53:22.032Z',
- buildNumber: 40,
- version: '1.0.0-build.40',
+ timestamp: '2026-04-15T19:47:05.026Z',
+ buildNumber: 46,
+ version: '1.0.0-build.46',
};
diff --git a/apps/wallet-server/.env.test b/apps/wallet-server/.env.test
new file mode 100644
index 0000000..2a6271e
--- /dev/null
+++ b/apps/wallet-server/.env.test
@@ -0,0 +1,9 @@
+# Truvera API Configuration
+TRUVERA_API_KEY=eyJzY29wZXMiOlsidGVzdCIsImFsbCJdLCJzdWIiOiIyMTYyNiIsInNlbGVjdGVkVGVhbUlkIjowLCJjcmVhdG9ySWQiOiIyMyIsImZtdCI6MSwiaWF0IjoxNzczNzcwNDU2LCJleHAiOjQ4NTMwNjY0NTZ9.K9TIa50Saw4SC63PGPWVWQw21dxq06awpL6vhhqs2igmWOxiWexNxF3f8hRmebEAchEhUKeBpq07dbU2fHEZAw
+TRUVERA_API_ENDPOINT=https://api-testnet.truvera.io
+
+# Node environment
+NODE_ENV=development
+TRUVERA_API_ISSUER_DID=did:cheqd:testnet:74e21607-cb71-4751-a79e-1b9a2a8aa986
+
+TRUVERA_RUN_LIVE_TESTS=true
diff --git a/apps/wallet-server/Dockerfile b/apps/wallet-server/Dockerfile
new file mode 100644
index 0000000..24f9023
--- /dev/null
+++ b/apps/wallet-server/Dockerfile
@@ -0,0 +1,69 @@
+# Multi-stage build for Wallet MCP Service
+ARG BUILD_NUMBER=1
+
+FROM node:22-alpine3.23 AS builder
+
+ARG BUILD_NUMBER
+
+WORKDIR /app
+
+RUN apk update && apk upgrade --no-cache && \
+ apk add --no-cache openssl
+
+RUN npm install -g patch-package@8.0.1
+
+COPY package*.json ./
+COPY scripts ./scripts
+COPY packages/mcp-shared/package*.json ./packages/mcp-shared/
+COPY apps/wallet-server/package*.json ./apps/wallet-server/
+COPY apps/wallet-server/patches ./apps/wallet-server/patches
+
+RUN npm ci --workspaces
+
+COPY packages/mcp-shared ./packages/mcp-shared
+RUN npm run build --workspace=packages/mcp-shared
+
+COPY apps/wallet-server/src ./apps/wallet-server/src
+COPY apps/wallet-server/scripts ./apps/wallet-server/scripts
+COPY apps/wallet-server/register-aliases.cjs ./apps/wallet-server/
+COPY apps/wallet-server/tsconfig.json ./apps/wallet-server/
+
+RUN BUILD_NUMBER=$BUILD_NUMBER npm run build --workspace=apps/wallet-server
+
+FROM node:22-alpine3.23
+
+WORKDIR /app
+
+RUN apk update && apk upgrade --no-cache && \
+ apk add --no-cache openssl
+
+RUN npm install -g patch-package@8.0.1
+
+COPY package*.json ./
+COPY scripts ./scripts
+COPY LICENSE /licenses/LICENSE
+COPY packages/mcp-shared/package*.json ./packages/mcp-shared/
+COPY apps/wallet-server/package*.json ./apps/wallet-server/
+COPY apps/wallet-server/patches ./apps/wallet-server/patches
+
+RUN npm ci --workspaces --omit=dev
+
+RUN rm -rf /usr/local/lib/node_modules/npm \
+ && rm -f /usr/local/bin/npm /usr/local/bin/npx
+
+COPY --from=builder /app/packages/mcp-shared/dist ./packages/mcp-shared/dist
+COPY --from=builder /app/packages/mcp-shared/package.json ./packages/mcp-shared/
+COPY --from=builder /app/apps/wallet-server/dist ./apps/wallet-server/dist
+COPY --from=builder /app/apps/wallet-server/register-aliases.cjs ./apps/wallet-server/register-aliases.cjs
+
+RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
+USER nodejs
+
+WORKDIR /app/apps/wallet-server
+
+EXPOSE 3001
+
+HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
+ CMD node -e "fetch('http://127.0.0.1:3001/health').then((response) => process.exit(response.ok ? 0 : 1)).catch(() => process.exit(1))"
+
+CMD ["node", "-r", "./register-aliases.cjs", "dist/index.js"]
\ No newline at end of file
diff --git a/apps/wallet-server/README.md b/apps/wallet-server/README.md
index 9170a14..aaedd96 100644
--- a/apps/wallet-server/README.md
+++ b/apps/wallet-server/README.md
@@ -20,14 +20,13 @@ A Model Context Protocol (MCP) server for interacting with the Truvera Wallet SD
| Credential management | ⏳ Planned |
| DIDComm messaging | ⏳ Planned |
| Tests | ⏳ Minimal |
-| Docker support | ⏳ Not yet |
+| Docker support | ✅ Included |
| Production hardening | ⏳ Not yet |
### Known limitations
- **In-memory storage only:** The current wallet-server wiring uses in-memory local storage adapters. This is suitable for development and tests, but persistence and cloud sync hardening are still pending.
-- **No Docker image:** There is no Dockerfile yet. The server can only be run locally via Node.js.
-- **No CI coverage:** The wallet-server is not yet included in automated CI tests.
+- **Local-only wallet state:** Containerized runs are useful for MCP integration testing, but the wallet still uses in-memory backing stores today.
---
@@ -54,6 +53,12 @@ cp .env.example .env
npm run build
```
+From the repo root you can also use:
+
+```bash
+npm run build:wallet
+```
+
### 4. Run
```bash
@@ -67,6 +72,38 @@ MCP_MODE=stdio npm start
npm run dev
```
+From the repo root:
+
+```bash
+npm run dev:wallet
+```
+
+### 5. Docker workflow
+
+From the repo root:
+
+```bash
+# Build the image
+npm run docker:build:wallet
+
+# Start the container in HTTP mode on port 3001
+npm run docker:run:wallet
+```
+
+Or from this directory:
+
+```bash
+docker-compose up -d
+```
+
+### 6. Verify the server is running
+
+```bash
+curl http://localhost:3001/health
+```
+
+If port 3001 is already in use and you start the server from an interactive terminal, the server now prompts to continue on the next available port instead of exiting immediately.
+
### MCP Inspector (shared docs)
Use the shared MCP Inspector instructions in the repo root README:
@@ -81,13 +118,26 @@ Use the shared MCP Inspector instructions in the repo root README:
|----------|----------|---------|-------------|
| `WALLET_MASTER_KEY` | Yes | — | Master encryption key for the wallet |
| `MCP_MODE` | No | `stdio` | Transport: `http` or `stdio` |
-| `MCP_PORT` | No | `3010` | HTTP port (only used when `MCP_MODE=http`) |
+| `MCP_PORT` | No | `3001` | HTTP port (only used when `MCP_MODE=http`) |
| `CHEQD_NETWORK` | No | `testnet` | Cheqd network: `testnet` or `mainnet` |
| `EDV_STORAGE_URL` | No | `https://edv.dock.io` | EDV cloud storage endpoint |
| `WALLET_NAME` | No | `mcp-wallet` | Wallet label |
---
+## Running tests
+
+```bash
+# Unit tests
+npm test
+
+# Integration tests
+npm run test:integration
+
+# Type checking only
+npm run typecheck
+```
+
## Planned architecture
See [WALLET_MCP_PLAN.md](../../WALLET_MCP_PLAN.md) at the repo root for the full development plan.
diff --git a/apps/wallet-server/docker-compose.yml b/apps/wallet-server/docker-compose.yml
new file mode 100644
index 0000000..ab6bb16
--- /dev/null
+++ b/apps/wallet-server/docker-compose.yml
@@ -0,0 +1,24 @@
+version: '3.8'
+
+services:
+ wallet-mcp-service:
+ build:
+ context: ../..
+ dockerfile: apps/wallet-server/Dockerfile
+ container_name: wallet-mcp-service
+ environment:
+ - WALLET_MASTER_KEY=${WALLET_MASTER_KEY}
+ - MCP_MODE=${MCP_MODE:-http}
+ - MCP_PORT=3001
+ - CHEQD_NETWORK=${CHEQD_NETWORK:-testnet}
+ - WALLET_NAME=${WALLET_NAME:-mcp-wallet}
+ - NODE_ENV=production
+ ports:
+ - "3001:3001"
+ restart: unless-stopped
+ networks:
+ - mcp-network
+
+networks:
+ mcp-network:
+ driver: bridge
\ No newline at end of file
diff --git a/apps/wallet-server/eslint.config.js b/apps/wallet-server/eslint.config.js
new file mode 100644
index 0000000..1c2ef23
--- /dev/null
+++ b/apps/wallet-server/eslint.config.js
@@ -0,0 +1,50 @@
+import tseslint from '@typescript-eslint/eslint-plugin';
+import tsparser from '@typescript-eslint/parser';
+
+export default [
+ {
+ files: ['src/**/*.ts'],
+ languageOptions: {
+ parser: tsparser,
+ parserOptions: {
+ ecmaVersion: 2022,
+ sourceType: 'module',
+ },
+ globals: {
+ console: 'readonly',
+ process: 'readonly',
+ __dirname: 'readonly',
+ __filename: 'readonly',
+ Buffer: 'readonly',
+ NodeJS: 'readonly',
+ },
+ },
+ plugins: {
+ '@typescript-eslint': tseslint,
+ },
+ rules: {
+ ...tseslint.configs.recommended.rules,
+ '@typescript-eslint/no-unused-vars': [
+ 'error',
+ {
+ argsIgnorePattern: '^_',
+ varsIgnorePattern: '^_',
+ },
+ ],
+ '@typescript-eslint/no-explicit-any': 'warn',
+ '@typescript-eslint/explicit-function-return-type': 'off',
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
+ '@typescript-eslint/no-non-null-assertion': 'warn',
+ 'no-console': 'off',
+ },
+ },
+ {
+ ignores: [
+ 'dist/**',
+ 'node_modules/**',
+ '**/*.js',
+ 'coverage/**',
+ '.vscode/**',
+ ],
+ },
+];
\ No newline at end of file
diff --git a/apps/wallet-server/jest.integration.config.cjs b/apps/wallet-server/jest.integration.config.cjs
index cc85fdc..1a34223 100644
--- a/apps/wallet-server/jest.integration.config.cjs
+++ b/apps/wallet-server/jest.integration.config.cjs
@@ -22,6 +22,8 @@ module.exports = {
],
},
moduleNameMapper: {
+ // Resolve TypeScript ESM-style .js extension imports to their source .ts files
+ "^(\\.{1,2}/.*)\\.js$": "$1",
"^ky-universal$": "ky",
"^base58-universal$": "/../../node_modules/base58-universal/main.js",
"^base64url-universal$": "/../../node_modules/base64url-universal/lib/index.js",
diff --git a/apps/wallet-server/jest.setup.js b/apps/wallet-server/jest.setup.js
index 6d9f0f4..fab928a 100644
--- a/apps/wallet-server/jest.setup.js
+++ b/apps/wallet-server/jest.setup.js
@@ -7,3 +7,15 @@ jest.mock('@docknetwork/wallet-sdk-wasm/src/services/blockchain', () => ({
isBlockchainReady: true,
},
}));
+
+// The wallet SDK can emit late debug logs from background status updates.
+// Keep integration tests deterministic by silencing data-store logger output.
+jest.mock('@docknetwork/wallet-sdk-data-store/src/logger', () => ({
+ logger: {
+ debug: jest.fn(),
+ performance: jest.fn(),
+ error: jest.fn(),
+ warn: jest.fn(),
+ info: jest.fn(),
+ },
+}));
diff --git a/apps/wallet-server/package.json b/apps/wallet-server/package.json
index 336d6ac..bb02ce8 100644
--- a/apps/wallet-server/package.json
+++ b/apps/wallet-server/package.json
@@ -5,13 +5,18 @@
"type": "module",
"main": "dist/index.js",
"scripts": {
+ "prebuild": "node scripts/update-build-version.js",
"build": "tsc",
- "start": "node dist/index.js",
+ "start": "node -r ./register-aliases.cjs dist/index.js",
"dev": "tsx src/index.ts",
"typecheck": "tsc --noEmit",
+ "lint": "eslint . --ext .ts",
+ "lint:fix": "eslint . --ext .ts --fix",
"test": "vitest run src/features/credentials/tests/unit/credentials-tools.test.ts src/features/dids/tests/unit/dids-tools.test.ts",
"test:watch": "vitest src/features/credentials/tests/unit/credentials-tools.test.ts src/features/dids/tests/unit/dids-tools.test.ts",
- "test:integration": "jest --config jest.integration.config.cjs --runInBand"
+ "test:integration": "jest --config jest.integration.config.cjs --runInBand",
+ "docker:build": "cd ../.. && docker build --build-arg BUILD_NUMBER=\"$(cat apps/wallet-server/.buildnumber)\" -t truvera-wallet-mcp:latest -t truvera-wallet-mcp:$(cat apps/wallet-server/.buildnumber) -f apps/wallet-server/Dockerfile .",
+ "docker:run": "docker rm -f truvera-wallet-mcp || true && docker run -d --name truvera-wallet-mcp --env-file ./.env -e MCP_MODE=http -e MCP_PORT=3001 -p 3001:3001 truvera-wallet-mcp:latest"
},
"dependencies": {
"@truvera/mcp-shared": "file:../../packages/mcp-shared",
@@ -19,14 +24,18 @@
"@docknetwork/wallet-sdk-core": "^1.7.0",
"@docknetwork/wallet-sdk-data-store": "^1.7.0",
"@docknetwork/wallet-sdk-data-store-web": "^1.7.0",
- "dotenv": "^16.6.1"
+ "dotenv": "^16.6.1",
+ "module-alias": "^2.2.3"
},
"devDependencies": {
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@types/jest": "^29.5.14",
"@types/node": "^20.0.0",
+ "@typescript-eslint/eslint-plugin": "^8.56.1",
+ "@typescript-eslint/parser": "^8.56.1",
"babel-jest": "^29.7.0",
+ "eslint": "^10.0.2",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"tsx": "^4.7.0",
diff --git a/apps/wallet-server/patches/@digitalbazaar+did-io+1.1.0.patch b/apps/wallet-server/patches/@digitalbazaar+did-io+1.1.0.patch
new file mode 100644
index 0000000..74f5ed2
--- /dev/null
+++ b/apps/wallet-server/patches/@digitalbazaar+did-io+1.1.0.patch
@@ -0,0 +1,13 @@
+diff --git a/node_modules/@digitalbazaar/did-io/lib/CachedResolver.js b/node_modules/@digitalbazaar/did-io/lib/CachedResolver.js
+index bfd0673..e830d09 100644
+--- a/node_modules/@digitalbazaar/did-io/lib/CachedResolver.js
++++ b/node_modules/@digitalbazaar/did-io/lib/CachedResolver.js
+@@ -2,7 +2,7 @@
+ * Copyright (c) 2021 Digital Bazaar, Inc. All rights reserved.
+ */
+ import {parseDid} from './did-io.js';
+-import {LruCache} from '@digitalbazaar/lru-memoize';
++import {LruCache} from '@digitalbazaar/lru-memoize/lib/main.js';
+
+ export class CachedResolver {
+ /**
diff --git a/apps/wallet-server/patches/@digitalbazaar+did-method-key+2.0.0.patch b/apps/wallet-server/patches/@digitalbazaar+did-method-key+2.0.0.patch
new file mode 100644
index 0000000..c1d3025
--- /dev/null
+++ b/apps/wallet-server/patches/@digitalbazaar+did-method-key+2.0.0.patch
@@ -0,0 +1,24 @@
+diff --git a/node_modules/@digitalbazaar/did-method-key/lib/DidKeyDriver.js b/node_modules/@digitalbazaar/did-method-key/lib/DidKeyDriver.js
+index 7e25886..d879c5a 100644
+--- a/node_modules/@digitalbazaar/did-method-key/lib/DidKeyDriver.js
++++ b/node_modules/@digitalbazaar/did-method-key/lib/DidKeyDriver.js
+@@ -3,15 +3,15 @@
+ */
+ import {
+ Ed25519VerificationKey2020
+-} from '@digitalbazaar/ed25519-verification-key-2020';
++} from '@digitalbazaar/ed25519-verification-key-2020/lib/main.js';
+ import {
+ X25519KeyAgreementKey2020
+-} from '@digitalbazaar/x25519-key-agreement-key-2020';
++} from '@digitalbazaar/x25519-key-agreement-key-2020/lib/main.js';
+ import {
+ X25519KeyAgreementKey2019
+-} from '@digitalbazaar/x25519-key-agreement-key-2019';
++} from '@digitalbazaar/x25519-key-agreement-key-2019/lib/main.js';
+
+-import * as didIo from '@digitalbazaar/did-io';
++import * as didIo from '@digitalbazaar/did-io/lib/main.js';
+
+ const DID_CONTEXT_URL = 'https://www.w3.org/ns/did/v1';
+ // For backwards compat only, not actually importing this suite
diff --git a/apps/wallet-server/patches/@digitalbazaar+minimal-cipher+4.0.2.patch b/apps/wallet-server/patches/@digitalbazaar+minimal-cipher+4.0.2.patch
new file mode 100644
index 0000000..6d7f3f6
--- /dev/null
+++ b/apps/wallet-server/patches/@digitalbazaar+minimal-cipher+4.0.2.patch
@@ -0,0 +1,13 @@
+diff --git a/node_modules/@digitalbazaar/minimal-cipher/util.js b/node_modules/@digitalbazaar/minimal-cipher/util.js
+index 50a6441..71212d8 100644
+--- a/node_modules/@digitalbazaar/minimal-cipher/util.js
++++ b/node_modules/@digitalbazaar/minimal-cipher/util.js
+@@ -2,7 +2,7 @@
+ import {TextDecoder, TextEncoder} from 'util';
+ export {TextDecoder, TextEncoder};
+
+-export {ReadableStream, TransformStream} from 'web-streams-polyfill/ponyfill';
++export {ReadableStream, TransformStream} from 'web-streams-polyfill/dist/ponyfill.js';
+
+ export function stringToUint8Array(data) {
+ if(typeof data === 'string') {
diff --git a/apps/wallet-server/patches/base58-universal+1.0.0.patch b/apps/wallet-server/patches/base58-universal+1.0.0.patch
new file mode 100644
index 0000000..9708bee
--- /dev/null
+++ b/apps/wallet-server/patches/base58-universal+1.0.0.patch
@@ -0,0 +1,126 @@
+diff --git a/node_modules/base58-universal/index.js b/node_modules/base58-universal/index.js
+index c1ff223..8f49bcc 100644
+--- a/node_modules/base58-universal/index.js
++++ b/node_modules/base58-universal/index.js
+@@ -3,6 +3,118 @@
+ */
+ 'use strict';
+
+-// translate `main.js` to CommonJS
+-require = require('esm')(module);
+-module.exports = require('./main.js');
++// Node 24 compatibility: avoid the legacy `esm` runtime shim.
++// This file provides a CommonJS implementation equivalent to `main.js`.
++const alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
++const reverseAlphabets = Object.create(null);
++
++function encodeBaseN(input, alphabetValue, maxline) {
++ if(!(input instanceof Uint8Array)) {
++ throw new TypeError('"input" must be a Uint8Array.');
++ }
++ if(typeof alphabetValue !== 'string') {
++ throw new TypeError('"alphabet" must be a string.');
++ }
++ if(maxline !== undefined && typeof maxline !== 'number') {
++ throw new TypeError('"maxline" must be a number.');
++ }
++ if(input.length === 0) {
++ return '';
++ }
++
++ let output = '';
++ const base = alphabetValue.length;
++ const first = alphabetValue.charAt(0);
++ const digits = [0];
++
++ for(let i = 0; i < input.length; ++i) {
++ let carry = input[i];
++ for(let j = 0; j < digits.length; ++j) {
++ carry += digits[j] << 8;
++ digits[j] = carry % base;
++ carry = (carry / base) | 0;
++ }
++
++ while(carry > 0) {
++ digits.push(carry % base);
++ carry = (carry / base) | 0;
++ }
++ }
++
++ for(let i = 0; input[i] === 0 && i < input.length - 1; ++i) {
++ output += first;
++ }
++ for(let i = digits.length - 1; i >= 0; --i) {
++ output += alphabetValue[digits[i]];
++ }
++
++ if(maxline) {
++ const regex = new RegExp('.{1,' + maxline + '}', 'g');
++ output = output.match(regex).join('\r\n');
++ }
++
++ return output;
++}
++
++function decodeBaseN(input, alphabetValue) {
++ if(typeof input !== 'string') {
++ throw new TypeError('"input" must be a string.');
++ }
++ if(typeof alphabetValue !== 'string') {
++ throw new TypeError('"alphabet" must be a string.');
++ }
++ if(input.length === 0) {
++ return new Uint8Array();
++ }
++
++ let table = reverseAlphabets[alphabetValue];
++ if(!table) {
++ table = reverseAlphabets[alphabetValue] = [];
++ for(let i = 0; i < alphabetValue.length; ++i) {
++ table[alphabetValue.charCodeAt(i)] = i;
++ }
++ }
++
++ input = input.replace(/\s/g, '');
++
++ const base = alphabetValue.length;
++ const first = alphabetValue.charAt(0);
++ const bytes = [0];
++ for(let i = 0; i < input.length; i++) {
++ const value = table[input.charCodeAt(i)];
++ if(value === undefined) {
++ return;
++ }
++
++ let carry = value;
++ for(let j = 0; j < bytes.length; ++j) {
++ carry += bytes[j] * base;
++ bytes[j] = carry & 0xff;
++ carry >>= 8;
++ }
++
++ while(carry > 0) {
++ bytes.push(carry & 0xff);
++ carry >>= 8;
++ }
++ }
++
++ for(let k = 0; input[k] === first && k < input.length - 1; ++k) {
++ bytes.push(0);
++ }
++
++ return new Uint8Array(bytes.reverse());
++}
++
++function encode(input, maxline) {
++ return encodeBaseN(input, alphabet, maxline);
++}
++
++function decode(input) {
++ return decodeBaseN(input, alphabet);
++}
++
++module.exports = {
++ encode,
++ decode,
++};
diff --git a/apps/wallet-server/register-aliases.cjs b/apps/wallet-server/register-aliases.cjs
new file mode 100644
index 0000000..07a86d2
--- /dev/null
+++ b/apps/wallet-server/register-aliases.cjs
@@ -0,0 +1,16 @@
+const path = require("path");
+const moduleAlias = require("module-alias");
+
+const rootNodeModules = path.resolve(__dirname, "../../node_modules");
+
+moduleAlias.addAliases({
+ "@digitalbazaar/did-method-key": path.join(rootNodeModules, "@digitalbazaar/did-method-key/lib/main.js"),
+ "@digitalbazaar/did-io": path.join(rootNodeModules, "@digitalbazaar/did-io/lib/main.js"),
+ "@digitalbazaar/minimal-cipher": path.join(rootNodeModules, "@digitalbazaar/minimal-cipher/Cipher.js"),
+ "@digitalbazaar/x25519-key-agreement-key-2020": path.join(rootNodeModules, "@digitalbazaar/x25519-key-agreement-key-2020/lib/main.js"),
+ "@digitalbazaar/x25519-key-agreement-key-2019": path.join(rootNodeModules, "@digitalbazaar/x25519-key-agreement-key-2019/lib/main.js"),
+ "@digitalbazaar/ed25519-verification-key-2020": path.join(rootNodeModules, "@digitalbazaar/ed25519-verification-key-2020/lib/main.js"),
+ "@digitalbazaar/ed25519-verification-key-2018": path.join(rootNodeModules, "@digitalbazaar/ed25519-verification-key-2018/src/main.js"),
+ // Force modern CJS build to avoid legacy `esm` wrapper crashes on Node 24.
+ "@digitalbazaar/http-client": path.join(rootNodeModules, "jsonld/node_modules/@digitalbazaar/http-client/dist/cjs/index.cjs"),
+});
diff --git a/apps/wallet-server/scripts/update-build-version.js b/apps/wallet-server/scripts/update-build-version.js
new file mode 100644
index 0000000..f9d6c8d
--- /dev/null
+++ b/apps/wallet-server/scripts/update-build-version.js
@@ -0,0 +1,38 @@
+#!/usr/bin/env node
+
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const buildInfoPath = path.join(__dirname, '../src/build-info.ts');
+const buildNumberPath = path.join(__dirname, '../.buildnumber');
+
+let buildNumber = process.env.BUILD_NUMBER ? parseInt(process.env.BUILD_NUMBER, 10) : null;
+
+if (!buildNumber || isNaN(buildNumber)) {
+ if (fs.existsSync(buildNumberPath)) {
+ const content = fs.readFileSync(buildNumberPath, 'utf-8').trim();
+ buildNumber = parseInt(content, 10) || 1;
+ buildNumber++;
+ } else {
+ buildNumber = 1;
+ }
+
+ fs.writeFileSync(buildNumberPath, String(buildNumber), 'utf-8');
+}
+
+const timestamp = new Date().toISOString();
+const packageVersion = process.env.npm_package_version || '0.1.0';
+const fullVersion = `${packageVersion}-build.${buildNumber}`;
+
+const buildInfo = `// Auto-generated build information
+export const BUILD_INFO = {
+ timestamp: '${timestamp}',
+ buildNumber: ${buildNumber},
+ version: '${fullVersion}',
+};
+`;
+
+fs.writeFileSync(buildInfoPath, buildInfo, 'utf-8');
+console.log(`✓ Updated build info: Version ${fullVersion} (${timestamp})`);
\ No newline at end of file
diff --git a/apps/wallet-server/src/build-info.ts b/apps/wallet-server/src/build-info.ts
index cbf4561..67a3a39 100644
--- a/apps/wallet-server/src/build-info.ts
+++ b/apps/wallet-server/src/build-info.ts
@@ -1,7 +1,6 @@
-import type { BuildInfo } from "@truvera/mcp-shared/types";
-
-export const BUILD_INFO: BuildInfo = {
- version: "0.1.0",
- buildNumber: 1,
- timestamp: new Date().toISOString(),
+// Auto-generated build information
+export const BUILD_INFO = {
+ timestamp: '2026-04-15T19:47:06.099Z',
+ buildNumber: 14,
+ version: '0.1.0-build.14',
};
diff --git a/apps/wallet-server/src/features/credentials/client.ts b/apps/wallet-server/src/features/credentials/client.ts
index 6fa1770..6851563 100644
--- a/apps/wallet-server/src/features/credentials/client.ts
+++ b/apps/wallet-server/src/features/credentials/client.ts
@@ -3,9 +3,7 @@
* Manages credential operations using the Dock Wallet SDK
*/
-import { createCredentialProvider } from "@docknetwork/wallet-sdk-core/lib/credential-provider";
-import { createDIDProvider } from "@docknetwork/wallet-sdk-core/lib/did-provider";
-import type { IWallet, ICredentialProvider, IDIDProvider } from "@docknetwork/wallet-sdk-core/lib/types";
+import type { IWallet, ICredentialProvider, IDIDProvider } from "@docknetwork/wallet-sdk-core/lib/types.js";
import type { CredentialListResult, CredentialInfo, ImportCredentialResult } from "./types.js";
export class CredentialClient {
@@ -21,8 +19,9 @@ export class CredentialClient {
/**
* Initialize the credential provider
*/
- private ensureProvider(): ICredentialProvider {
+ private async ensureProvider(): Promise {
if (!this.credentialProvider) {
+ const { createCredentialProvider } = await import("@docknetwork/wallet-sdk-core/lib/credential-provider.js");
this.credentialProvider = createCredentialProvider({ wallet: this.wallet });
}
return this.credentialProvider;
@@ -31,8 +30,9 @@ export class CredentialClient {
/**
* Initialize the DID provider (required for credential import)
*/
- private ensureDIDProvider(): IDIDProvider {
+ private async ensureDIDProvider(): Promise {
if (!this.didProvider) {
+ const { createDIDProvider } = await import("@docknetwork/wallet-sdk-core/lib/did-provider.js");
this.didProvider = createDIDProvider({ wallet: this.wallet });
}
return this.didProvider;
@@ -43,8 +43,8 @@ export class CredentialClient {
*/
async importCredential(uri: string): Promise {
try {
- const credentialProvider = this.ensureProvider();
- const didProvider = this.ensureDIDProvider();
+ const credentialProvider = await this.ensureProvider();
+ const didProvider = await this.ensureDIDProvider();
const before = await credentialProvider.getCredentials();
const beforeIds = new Set(before.map((doc: any) => doc?.id).filter(Boolean));
@@ -96,7 +96,7 @@ export class CredentialClient {
* List all credentials in the wallet
*/
async listCredentials(): Promise {
- const provider = this.ensureProvider();
+ const provider = await this.ensureProvider();
const allDocs = await provider.getCredentials();
// Map credentials to our standardized format
diff --git a/apps/wallet-server/src/features/credentials/tests/integration/credential-proof-response.e2e.test.ts b/apps/wallet-server/src/features/credentials/tests/integration/credential-proof-response.e2e.test.ts
new file mode 100644
index 0000000..0793a05
--- /dev/null
+++ b/apps/wallet-server/src/features/credentials/tests/integration/credential-proof-response.e2e.test.ts
@@ -0,0 +1,183 @@
+/**
+ * Live end-to-end test for the proof request response flow, exercised through
+ * the MCP tool handler layer.
+ *
+ * Flow:
+ * 1) Create a DID via the `create_did` tool handler
+ * 2) Import a credential via the `import_credential` tool handler
+ * 3) Create a proof request from the predefined template via Truvera API (direct HTTP)
+ * 4) Respond to the proof request via the `respond_to_proof_request` tool handler
+ * → builds and returns a verifiable presentation
+ * 5) Verify the presentation via Truvera /verify (direct HTTP)
+ * → the presentation must pass verification
+ *
+ * Requirements:
+ * TRUVERA_RUN_LIVE_TESTS=true
+ * TRUVERA_API_KEY=
+ *
+ * Run via: npm run test:integration
+ */
+
+import { describe, it, expect, beforeAll, afterAll } from "@jest/globals";
+
+import { WalletClient } from "../../../../wallet-client";
+import { DIDClient } from "../../../dids/client";
+import { CredentialClient } from "../../client";
+import { getDIDHandlers } from "../../../dids/tools";
+import { getCredentialHandlers } from "../../tools";
+import { requireLiveTestEnv, TRUVERA_API_ENDPOINT, liveApiKey } from "../../../../tests/helpers/live-test-gate";
+
+// ── Constants ────────────────────────────────────────────────────────────────
+
+const OID4VCI_TEST_OFFER_URI =
+ "openid-credential-offer://?credential_offer_uri=https://api-testnet.truvera.io/openid/credential-offers/f3a5398e-e991-4ff8-9e45-7c29873cc39b";
+const PROOF_TEMPLATE_ID = "caa741b3-aa21-4bbc-b51d-e82148a7e435";
+
+// ── Helpers ───────────────────────────────────────────────────────────────────
+
+/** Parse the text content from an MCP tool handler response. */
+function parseToolResult(result: unknown): unknown {
+ const r = result as any;
+ const text = r?.content?.[0]?.text;
+ if (typeof text !== "string") {
+ throw new Error(`Unexpected tool result shape: ${JSON.stringify(result)}`);
+ }
+ return JSON.parse(text);
+}
+
+/**
+ * Call the Truvera API to create a fresh proof request from the given template.
+ * Returns the full proof request object (the document the wallet SDK needs to
+ * feed into the verification controller).
+ */
+async function createProofRequestFromTemplate(templateId: string): Promise> {
+ const response = await fetch(
+ `${TRUVERA_API_ENDPOINT}/proof-templates/${encodeURIComponent(templateId)}/request`,
+ {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${liveApiKey}`,
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ name: `wallet-proof-response-e2e-${Date.now()}` }),
+ }
+ );
+
+ const raw = await response.text();
+ if (!response.ok) {
+ throw new Error(`Failed to create proof request (${response.status}): ${raw}`);
+ }
+
+ const parsed: any = JSON.parse(raw);
+ // The API may return the proof-request object directly, or nested under a key.
+ const candidates: unknown[] = [parsed, parsed?.data, parsed?.proofRequest, parsed?.request];
+ const proofRequest = candidates.find(
+ (c) => c && typeof c === "object" && typeof (c as any).request === "object"
+ ) as Record | undefined;
+
+ if (!proofRequest) {
+ throw new Error(`Proof request object not found in API response: ${raw}`);
+ }
+
+ return proofRequest;
+}
+
+/**
+ * Verify a presentation via Truvera /verify.
+ * Tries the plain presentation first, then common wrapper shapes.
+ */
+async function verifyPresentation(presentation: unknown): Promise<{ verified: boolean }> {
+ const payloads = [presentation, { data: presentation }];
+ let lastBody = "";
+
+ for (const payload of payloads) {
+ const response = await fetch(`${TRUVERA_API_ENDPOINT}/verify`, {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${liveApiKey}`,
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(payload),
+ });
+
+ const raw = await response.text();
+ lastBody = raw;
+
+ if (!response.ok) continue;
+
+ const parsed: any = JSON.parse(raw);
+ const candidates: unknown[] = [parsed, parsed?.data, parsed?.result, parsed?.data?.result];
+ for (const c of candidates) {
+ if (c && typeof c === "object" && typeof (c as any).verified === "boolean") {
+ return { verified: (c as any).verified };
+ }
+ }
+ }
+
+ throw new Error(`Unable to determine verified status from /verify response. Last body: ${lastBody}`);
+}
+
+// ── Test suite ────────────────────────────────────────────────────────────────
+
+describe("e2e: credential import → proof request response (via MCP tool handlers)", () => {
+ let walletClient: WalletClient;
+ let handlers: Map Promise>;
+
+ beforeAll(async () => {
+ requireLiveTestEnv();
+
+ const uniqueWalletName = `proof-e2e-wallet-${Date.now()}-${Math.random()}`;
+ walletClient = new WalletClient(uniqueWalletName, "testnet");
+
+ const wallet = await walletClient.initialize();
+ const didClient = new DIDClient(wallet);
+ const credentialClient = new CredentialClient(wallet);
+
+ handlers = new Map([
+ ...getDIDHandlers(didClient),
+ ...getCredentialHandlers(credentialClient),
+ ]) as Map Promise>;
+ });
+
+ afterAll(async () => {
+ if (walletClient) {
+ await walletClient.waitForIdle();
+ }
+ if (walletClient?.isInitialized()) {
+ try {
+ await walletClient.deleteWallet();
+ await walletClient.waitForIdle();
+ } catch (error) {
+ console.error("Error cleaning up wallet:", error);
+ }
+ }
+ });
+
+ it("creates a DID, imports a credential, responds to a proof request, and the presentation verifies", async () => {
+ // ── Step 1: create a DID ─────────────────────────────────────────────────
+ const createDIDResult = parseToolResult(await handlers.get("create_did")!({})) as any;
+ expect(createDIDResult.success).toBe(true);
+ expect(createDIDResult.did).toMatch(/^did:/);
+
+ // ── Step 2: import credential ────────────────────────────────────────────
+ const importResult = parseToolResult(
+ await handlers.get("import_credential")!({ uri: OID4VCI_TEST_OFFER_URI })
+ ) as any;
+ expect(importResult.success).toBe(true);
+
+ // ── Step 3: create proof request via Truvera API ─────────────────────────
+ const proofRequest = await createProofRequestFromTemplate(PROOF_TEMPLATE_ID);
+ expect(proofRequest).toBeDefined();
+
+ // ── Step 4: respond to proof request via MCP tool (not yet implemented) ──
+ const presentationResult = parseToolResult(
+ await handlers.get("respond_to_proof_request")!({ proofRequest })
+ ) as any;
+ expect(presentationResult.success).toBe(true);
+ expect(presentationResult.presentation).toBeDefined();
+
+ // ── Step 5: verify the presentation ─────────────────────────────────────
+ const verification = await verifyPresentation(presentationResult.presentation);
+ expect(verification.verified).toBe(true);
+ });
+});
diff --git a/apps/wallet-server/src/features/credentials/tests/integration/credentials-client.test.ts b/apps/wallet-server/src/features/credentials/tests/integration/credentials-client.test.ts
index ba67d14..f87957f 100644
--- a/apps/wallet-server/src/features/credentials/tests/integration/credentials-client.test.ts
+++ b/apps/wallet-server/src/features/credentials/tests/integration/credentials-client.test.ts
@@ -7,10 +7,15 @@ import { describe, it, expect, beforeEach, afterEach } from "@jest/globals";
import { WalletClient } from "../../../../wallet-client";
import { CredentialClient } from "../../client";
+import { DIDClient } from "../../../dids/client";
+
+const OID4VCI_TEST_OFFER_URI =
+ "openid-credential-offer://?credential_offer_uri=https://api-testnet.truvera.io/openid/credential-offers/fbe0a6ed-2aa8-4363-833b-6aa8fe1c6d01";
describe("integration: CredentialClient with real Wallet SDK", () => {
let walletClient: WalletClient;
let credentialClient: CredentialClient;
+ let didClient: DIDClient;
beforeEach(async () => {
// Create a unique wallet for each test to avoid conflicts
@@ -20,19 +25,23 @@ describe("integration: CredentialClient with real Wallet SDK", () => {
// Initialize wallet and credential client
const wallet = await walletClient.initialize();
credentialClient = new CredentialClient(wallet);
+ didClient = new DIDClient(wallet);
});
afterEach(async () => {
+ if (walletClient) {
+ await walletClient.waitForIdle();
+ }
+
// Clean up wallet resources after each test
if (walletClient && walletClient.isInitialized()) {
try {
await walletClient.deleteWallet();
+ await walletClient.waitForIdle();
} catch (error) {
console.error("Error cleaning up wallet:", error);
}
}
- // Wait for remaining async operations to complete
- await new Promise((resolve) => setTimeout(resolve, 100));
});
describe("listCredentials", () => {
@@ -85,4 +94,82 @@ describe("integration: CredentialClient with real Wallet SDK", () => {
expect(result.count).toBeGreaterThanOrEqual(0);
});
});
+
+ describe("importCredential", () => {
+ it("returns success: false with a message when URI is malformed", async () => {
+ const result = await credentialClient.importCredential("not-a-valid-uri");
+
+ expect(result.success).toBe(false);
+ expect(typeof result.message).toBe("string");
+ expect(result.message!.length).toBeGreaterThan(0);
+ expect(result.credential).toBeUndefined();
+ });
+
+ it("returns success: false when the credential offer URI is unreachable", async () => {
+ const result = await credentialClient.importCredential(
+ "openid-credential-offer://?credential_offer_uri=https://localhost:19999/offer/does-not-exist"
+ );
+
+ expect(result.success).toBe(false);
+ expect(typeof result.message).toBe("string");
+ expect(result.message!.length).toBeGreaterThan(0);
+ });
+
+ it("does not alter the credential list after a failed import", async () => {
+ const before = await credentialClient.listCredentials();
+
+ await credentialClient.importCredential("not-a-valid-uri");
+
+ const after = await credentialClient.listCredentials();
+ expect(after.count).toBe(before.count);
+ });
+
+ it("initialises the DID provider lazily alongside the credential provider", async () => {
+ // Calling importCredential bootstraps both providers internally.
+ // A second call should reuse them without error.
+ const first = await credentialClient.importCredential("not-a-valid-uri");
+ const second = await credentialClient.importCredential("not-a-valid-uri");
+
+ expect(first.success).toBe(false);
+ expect(second.success).toBe(false);
+ });
+
+ it("result always conforms to ImportCredentialResult shape", async () => {
+ const result = await credentialClient.importCredential("bad-uri");
+
+ expect(result).toHaveProperty("success");
+ expect(typeof result.success).toBe("boolean");
+ // message is present on failure
+ expect(result).toHaveProperty("message");
+ });
+
+ it("imports credential from OID4VCI offer URL and stores it in the wallet SDK", async () => {
+ // Ensure the wallet has a DID available before import.
+ await didClient.createDID();
+
+ const before = await credentialClient.listCredentials();
+
+ const importResult = await credentialClient.importCredential(OID4VCI_TEST_OFFER_URI);
+ expect(importResult.success).toBe(true);
+ expect(importResult.credential).toBeDefined();
+
+ const after = await credentialClient.listCredentials();
+ expect(after.count).toBeGreaterThan(before.count);
+
+ // Verify the imported credential is visible via wallet-sdk provider storage too.
+ const { createCredentialProvider } = await import("@docknetwork/wallet-sdk-core/lib/credential-provider.js");
+ const provider = createCredentialProvider({ wallet: walletClient.getWallet() });
+ const sdkCredentials = await provider.getCredentials();
+ expect(sdkCredentials.length).toBeGreaterThan(0);
+
+ const importedId = importResult.credential?.id;
+ if (importedId) {
+ const inSdkStore = sdkCredentials.some((doc: any) => {
+ const id = doc?.id || doc?.credential?.id;
+ return id === importedId;
+ });
+ expect(inSdkStore).toBe(true);
+ }
+ });
+ });
});
diff --git a/apps/wallet-server/src/features/dids/client.ts b/apps/wallet-server/src/features/dids/client.ts
index c18a2a5..16abc6f 100644
--- a/apps/wallet-server/src/features/dids/client.ts
+++ b/apps/wallet-server/src/features/dids/client.ts
@@ -3,9 +3,8 @@
* Manages DID operations using the Dock Wallet SDK
*/
-import { createDIDProvider } from "@docknetwork/wallet-sdk-core/lib/did-provider";
-import type { IDIDProvider } from "@docknetwork/wallet-sdk-core/lib/types";
-import type { IWallet } from "@docknetwork/wallet-sdk-core/lib/types";
+import type { IDIDProvider } from "@docknetwork/wallet-sdk-core/lib/types.js";
+import type { IWallet } from "@docknetwork/wallet-sdk-core/lib/types.js";
import type { CreateDIDResult, DIDListResult } from "./types.js";
export class DIDClient {
@@ -19,8 +18,9 @@ export class DIDClient {
/**
* Initialize the DID provider
*/
- private ensureProvider(): IDIDProvider {
+ private async ensureProvider(): Promise {
if (!this.didProvider) {
+ const { createDIDProvider } = await import("@docknetwork/wallet-sdk-core/lib/did-provider.js");
this.didProvider = createDIDProvider({ wallet: this.wallet });
}
return this.didProvider;
@@ -30,7 +30,7 @@ export class DIDClient {
* Get the default DID for this wallet
*/
async getDefaultDID(): Promise {
- const provider = this.ensureProvider();
+ const provider = await this.ensureProvider();
const allDocs = await provider.getAll();
// Filter to only DID resolution documents and extract the DID
@@ -46,7 +46,7 @@ export class DIDClient {
* Create a new DID
*/
async createDID(keyType?: string): Promise {
- const provider = this.ensureProvider();
+ const provider = await this.ensureProvider();
// Create DID using the provider
const result = await provider.createDIDKey({
@@ -65,7 +65,7 @@ export class DIDClient {
* List all DIDs in the wallet
*/
async listDIDs(): Promise {
- const provider = this.ensureProvider();
+ const provider = await this.ensureProvider();
const allDocs = await provider.getAll();
// Filter to only DID resolution documents and extract the DID
diff --git a/apps/wallet-server/src/features/dids/tests/integration/dids-client.test.ts b/apps/wallet-server/src/features/dids/tests/integration/dids-client.test.ts
index 91810f8..2142ccd 100644
--- a/apps/wallet-server/src/features/dids/tests/integration/dids-client.test.ts
+++ b/apps/wallet-server/src/features/dids/tests/integration/dids-client.test.ts
@@ -23,6 +23,10 @@ describe("integration: DIDClient with real Wallet SDK", () => {
});
afterEach(async () => {
+ if (walletClient) {
+ await walletClient.waitForIdle();
+ }
+
// Clean up wallet resources after each test
if (walletClient && walletClient.isInitialized()) {
try {
@@ -31,8 +35,6 @@ describe("integration: DIDClient with real Wallet SDK", () => {
console.error("Error cleaning up wallet:", error);
}
}
- // Wait for remaining async operations to complete
- await new Promise((resolve) => setTimeout(resolve, 100));
});
describe("getDefaultDID", () => {
diff --git a/apps/wallet-server/src/features/dids/tests/unit/dids-tools.test.ts b/apps/wallet-server/src/features/dids/tests/unit/dids-tools.test.ts
index ae93a85..52460ea 100644
--- a/apps/wallet-server/src/features/dids/tests/unit/dids-tools.test.ts
+++ b/apps/wallet-server/src/features/dids/tests/unit/dids-tools.test.ts
@@ -252,7 +252,7 @@ describe("unit: DID tools", () => {
});
// Test each handler returns proper structure
- for (const [name, handler] of handlers.entries()) {
+ for (const [_name, handler] of handlers.entries()) {
const result = await handler({});
expect(result).toHaveProperty("content");
diff --git a/apps/wallet-server/src/index.ts b/apps/wallet-server/src/index.ts
index cecc19e..a4f81bc 100644
--- a/apps/wallet-server/src/index.ts
+++ b/apps/wallet-server/src/index.ts
@@ -1,7 +1,6 @@
import "dotenv/config";
import { bootstrapMCPServer } from "@truvera/mcp-shared/server";
import { BUILD_INFO } from "./build-info.js";
-import { createDIDProvider } from "@docknetwork/wallet-sdk-core/lib/did-provider";
import { WalletClient } from "./wallet-client.js";
import { DIDClient, didToolDefs, getDIDHandlers } from "./features/dids/index.js";
import { CredentialClient, credentialToolDefs, getCredentialHandlers } from "./features/credentials/index.js";
@@ -26,10 +25,7 @@ async function initializeClients() {
const wallet = walletClient.getWallet();
const didClient = new DIDClient(wallet);
-
- // Create DID provider for credential import
- const didProvider = createDIDProvider({ wallet });
- const credentialClient = new CredentialClient(wallet, didProvider);
+ const credentialClient = new CredentialClient(wallet);
return { walletClient, didClient, credentialClient };
}
diff --git a/apps/wallet-server/src/tests/helpers/live-test-gate.ts b/apps/wallet-server/src/tests/helpers/live-test-gate.ts
new file mode 100644
index 0000000..c271b4e
--- /dev/null
+++ b/apps/wallet-server/src/tests/helpers/live-test-gate.ts
@@ -0,0 +1,31 @@
+import dotenv from "dotenv";
+
+dotenv.config();
+dotenv.config({ path: ".env.test", override: true });
+dotenv.config({ path: ".env.tests", override: true });
+
+const LIVE_MODE = process.env.TRUVERA_RUN_LIVE_TESTS === "true";
+const API_KEY = process.env.TRUVERA_API_KEY;
+
+export const TRUVERA_API_ENDPOINT =
+ process.env.TRUVERA_API_ENDPOINT || "https://api-testnet.truvera.io";
+
+export const liveApiKey = API_KEY;
+
+export const shouldRunLiveTests = LIVE_MODE && !!API_KEY;
+
+export const liveTestSkipReason = !LIVE_MODE
+ ? "TRUVERA_RUN_LIVE_TESTS=true is required to run live tests"
+ : !API_KEY
+ ? "TRUVERA_API_KEY is required to run live tests"
+ : undefined;
+
+/**
+ * Call at the start of a `beforeAll` to make the suite fail loudly instead of
+ * silently skipping when live-test env vars are not configured.
+ */
+export function requireLiveTestEnv(): void {
+ if (liveTestSkipReason) {
+ throw new Error(`Live test env not configured: ${liveTestSkipReason}`);
+ }
+}
diff --git a/apps/wallet-server/src/wallet-client.ts b/apps/wallet-server/src/wallet-client.ts
index da6c6c7..38e42ba 100644
--- a/apps/wallet-server/src/wallet-client.ts
+++ b/apps/wallet-server/src/wallet-client.ts
@@ -3,8 +3,8 @@
* Manages wallet initialization and lifecycle
*/
-import { createDataStore as createBaseDataStore } from "@docknetwork/wallet-sdk-data-store/lib/index";
-import type { DataStore, LocalStorage } from "@docknetwork/wallet-sdk-data-store/lib/types";
+import { createDataStore as createBaseDataStore } from "@docknetwork/wallet-sdk-data-store/lib/index.js";
+import type { DataStore, LocalStorage } from "@docknetwork/wallet-sdk-data-store/lib/types.js";
import {
createDocument,
removeDocument,
@@ -15,14 +15,14 @@ import {
getAllDocuments,
removeAllDocuments,
getDocumentCorrelations,
-} from "@docknetwork/wallet-sdk-data-store-web/lib/entities/document";
+} from "@docknetwork/wallet-sdk-data-store-web/lib/entities/document/index.js";
import {
createWallet as createWalletRecord,
getWallet,
updateWallet,
-} from "@docknetwork/wallet-sdk-data-store-web/lib/entities/wallet.entity";
-import { createWallet } from "@docknetwork/wallet-sdk-core/lib/wallet";
-import type { IWallet } from "@docknetwork/wallet-sdk-core/lib/types";
+} from "@docknetwork/wallet-sdk-data-store-web/lib/entities/wallet.entity.js";
+import { createWallet } from "@docknetwork/wallet-sdk-core/lib/wallet.js";
+import type { IWallet } from "@docknetwork/wallet-sdk-core/lib/types.js";
class InMemoryLocalStorage implements LocalStorage {
private readonly storage = new Map();
@@ -45,12 +45,64 @@ export class WalletClient {
private walletName: string;
private networkId: string;
private dataStore: DataStore | null = null;
+ private inFlightDocumentOps = 0;
+ private idleWaiters: Array<() => void> = [];
constructor(walletName: string = "default-wallet", networkId: string = "testnet") {
this.walletName = walletName;
this.networkId = networkId;
}
+ private trackDocumentOperation(operation: Promise): Promise {
+ this.inFlightDocumentOps += 1;
+
+ return operation.finally(() => {
+ this.inFlightDocumentOps = Math.max(0, this.inFlightDocumentOps - 1);
+
+ if (this.inFlightDocumentOps === 0) {
+ const waiters = this.idleWaiters.splice(0);
+ for (const resolve of waiters) {
+ resolve();
+ }
+ }
+ });
+ }
+
+ /**
+ * Wait until tracked document operations settle.
+ * This avoids brittle fixed sleeps in integration tests.
+ */
+ async waitForIdle(timeoutMs: number = 10000): Promise {
+ const start = Date.now();
+
+ while (true) {
+ if (this.inFlightDocumentOps === 0) {
+ // Ensure no new operations were queued in the same tick.
+ await new Promise((resolve) => setImmediate(resolve));
+ if (this.inFlightDocumentOps === 0) {
+ return;
+ }
+ }
+
+ const elapsed = Date.now() - start;
+ const remaining = timeoutMs - elapsed;
+ if (remaining <= 0) {
+ throw new Error(`Timed out waiting for wallet document operations to settle after ${timeoutMs}ms`);
+ }
+
+ await new Promise((resolve, reject) => {
+ const timeoutId = setTimeout(() => {
+ reject(new Error(`Timed out waiting for wallet document operations to settle after ${timeoutMs}ms`));
+ }, remaining);
+
+ this.idleWaiters.push(() => {
+ clearTimeout(timeoutId);
+ resolve();
+ });
+ });
+ }
+ }
+
/**
* Initialize the wallet
*/
@@ -75,14 +127,14 @@ export class WalletClient {
},
dataSource,
documentStore: {
- addDocument: (json, options) => createDocument({ dataStore, json, options }),
- removeDocument: (id, options) => removeDocument({ dataStore, id, options }),
- updateDocument: (document, options) => updateDocument({ dataStore, document, options }),
+ addDocument: (json, options) => this.trackDocumentOperation(createDocument({ dataStore, json, options })),
+ removeDocument: (id, options) => this.trackDocumentOperation(removeDocument({ dataStore, id, options })),
+ updateDocument: (document, options) => this.trackDocumentOperation(updateDocument({ dataStore, document, options })),
getDocumentById: (id) => getDocumentById({ dataStore, id }),
getDocumentsByType: (type) => getDocumentsByType({ dataStore, type }),
getDocumentsById: (idList) => getDocumentsById({ dataStore, idList }),
getAllDocuments: (allNetworks) => getAllDocuments({ dataStore, allNetworks }),
- removeAllDocuments: () => removeAllDocuments({ dataStore }),
+ removeAllDocuments: () => this.trackDocumentOperation(removeAllDocuments({ dataStore })),
getDocumentCorrelations: (documentId) => getDocumentCorrelations({ dataStore, documentId }),
},
localStorageImpl,
@@ -161,14 +213,13 @@ export class WalletClient {
// Call wallet cleanup
try {
+ await this.waitForIdle();
await this.wallet.deleteWallet();
+ await this.waitForIdle();
} catch (err) {
console.debug("Error in wallet.deleteWallet():", err);
}
- // Wait for async operations to settle before cleanup
- await new Promise((resolve) => setTimeout(resolve, 100));
-
// Null out references to allow garbage collection
this.wallet = null;
this.dataStore = null;
diff --git a/docker-compose.yml b/docker-compose.yml
index 69e1be2..5c1df35 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -18,6 +18,24 @@ services:
networks:
- mcp-network
+ wallet-mcp-service:
+ build:
+ context: .
+ dockerfile: apps/wallet-server/Dockerfile
+ container_name: wallet-mcp-service
+ environment:
+ - WALLET_MASTER_KEY=${WALLET_MASTER_KEY}
+ - MCP_MODE=${MCP_MODE:-http}
+ - MCP_PORT=3001
+ - CHEQD_NETWORK=${CHEQD_NETWORK:-testnet}
+ - WALLET_NAME=${WALLET_NAME:-mcp-wallet}
+ - NODE_ENV=production
+ ports:
+ - "3001:3001"
+ restart: unless-stopped
+ networks:
+ - mcp-network
+
networks:
mcp-network:
driver: bridge
diff --git a/package-lock.json b/package-lock.json
index b5b8723..37bfeb1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,10 +7,14 @@
"": {
"name": "truvera-mcp-servers",
"version": "1.0.0",
+ "hasInstallScript": true,
"workspaces": [
"packages/*",
"apps/*"
],
+ "devDependencies": {
+ "patch-package": "^8.0.1"
+ },
"engines": {
"node": ">=18.0.0",
"npm": ">=8.0.0"
@@ -311,17 +315,22 @@
"version": "0.1.0",
"dependencies": {
"@docknetwork/wallet-sdk-core": "^1.7.0",
+ "@docknetwork/wallet-sdk-data-store": "^1.7.0",
"@docknetwork/wallet-sdk-data-store-web": "^1.7.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"@truvera/mcp-shared": "file:../../packages/mcp-shared",
- "dotenv": "^16.6.1"
+ "dotenv": "^16.6.1",
+ "module-alias": "^2.2.3"
},
"devDependencies": {
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@types/jest": "^29.5.14",
"@types/node": "^20.0.0",
+ "@typescript-eslint/eslint-plugin": "^8.56.1",
+ "@typescript-eslint/parser": "^8.56.1",
"babel-jest": "^29.7.0",
+ "eslint": "^10.0.2",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"tsx": "^4.7.0",
@@ -723,6 +732,71 @@
"node": ">=12"
}
},
+ "apps/wallet-server/node_modules/@eslint/config-array": {
+ "version": "0.23.5",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz",
+ "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^3.0.5",
+ "debug": "^4.3.1",
+ "minimatch": "^10.2.4"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
+ "apps/wallet-server/node_modules/@eslint/config-helpers": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz",
+ "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^1.2.1"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
+ "apps/wallet-server/node_modules/@eslint/core": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz",
+ "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
+ "apps/wallet-server/node_modules/@eslint/object-schema": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz",
+ "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
+ "apps/wallet-server/node_modules/@eslint/plugin-kit": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz",
+ "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^1.2.1",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
"apps/wallet-server/node_modules/@vitest/expect": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.1.tgz",
@@ -797,6 +871,23 @@
"url": "https://opencollective.com/vitest"
}
},
+ "apps/wallet-server/node_modules/ajv": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
+ "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
"apps/wallet-server/node_modules/assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
@@ -807,6 +898,29 @@
"node": "*"
}
},
+ "apps/wallet-server/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "apps/wallet-server/node_modules/brace-expansion": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
+ "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
"apps/wallet-server/node_modules/chai": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz",
@@ -865,6 +979,145 @@
"@esbuild/win32-x64": "0.21.5"
}
},
+ "apps/wallet-server/node_modules/eslint": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.0.tgz",
+ "integrity": "sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.2",
+ "@eslint/config-array": "^0.23.4",
+ "@eslint/config-helpers": "^0.5.4",
+ "@eslint/core": "^1.2.0",
+ "@eslint/plugin-kit": "^0.7.0",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.14.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^9.1.2",
+ "eslint-visitor-keys": "^5.0.1",
+ "espree": "^11.2.0",
+ "esquery": "^1.7.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "minimatch": "^10.2.4",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "apps/wallet-server/node_modules/eslint-scope": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz",
+ "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@types/esrecurse": "^4.3.1",
+ "@types/estree": "^1.0.8",
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "apps/wallet-server/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "apps/wallet-server/node_modules/espree": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
+ "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.16.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^5.0.1"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "apps/wallet-server/node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "apps/wallet-server/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "apps/wallet-server/node_modules/minimatch": {
+ "version": "10.2.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.5"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"apps/wallet-server/node_modules/p-limit": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz",
@@ -2793,9 +3046,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
- "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
+ "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -2866,9 +3119,9 @@
}
},
"node_modules/@borewit/text-codec": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.1.tgz",
- "integrity": "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==",
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz",
+ "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==",
"license": "MIT",
"funding": {
"type": "github",
@@ -2881,39 +3134,45 @@
"integrity": "sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==",
"license": "(Apache-2.0 AND BSD-3-Clause)"
},
+ "node_modules/@cedar-policy/cedar-wasm": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@cedar-policy/cedar-wasm/-/cedar-wasm-4.9.1.tgz",
+ "integrity": "sha512-7+57EYkWmkBGasBQU6UhdafwxrY+YXzBlxpYZn33s1YR978W6ZqgLEAvHb3Wg1XMIzLWWoljhFYerejpOpvxuA==",
+ "license": "Apache-2.0"
+ },
"node_modules/@cheqd/sdk": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/@cheqd/sdk/-/sdk-5.3.2.tgz",
- "integrity": "sha512-JRvhj8BZllMWtQEZCO1YKs1/QhVufvZyTNmfwNLiPvNWhjwkCookxU6E8xn9Vs/tCeMgNxlfrJTkPWcdE2DlMA==",
+ "version": "5.4.3",
+ "resolved": "https://registry.npmjs.org/@cheqd/sdk/-/sdk-5.4.3.tgz",
+ "integrity": "sha512-ewi08YKsOkqwlYlHg8ocxOhuuXQQprq9+XoGY5ZR+5i3zpw2CggDHiSPfSjrF8EhVFk0JcMo3vfFRoksdjpb8w==",
"license": "Apache-2.0",
"workspaces": [
"esm",
"cjs"
],
"dependencies": {
- "@cheqd/ts-proto": "^4.1.1",
- "@cheqd/ts-proto-cjs": "npm:@cheqd/ts-proto@~2.5.0",
- "@cosmjs/amino": "^0.33.1",
+ "@cheqd/ts-proto": "^4.2.0",
+ "@cheqd/ts-proto-cjs": "npm:@cheqd/ts-proto@^2.6.0",
+ "@cosmjs/amino": "^0.36.2",
"@cosmjs/amino-cjs": "npm:@cosmjs/amino@~0.30.1",
- "@cosmjs/crypto": "^0.33.1",
+ "@cosmjs/crypto": "^0.36.2",
"@cosmjs/crypto-cjs": "npm:@cosmjs/crypto@~0.30.1",
- "@cosmjs/encoding": "^0.33.1",
+ "@cosmjs/encoding": "^0.36.2",
"@cosmjs/encoding-cjs": "npm:@cosmjs/encoding@~0.30.1",
- "@cosmjs/math": "^0.33.1",
+ "@cosmjs/math": "^0.36.2",
"@cosmjs/math-cjs": "npm:@cosmjs/math@~0.30.1",
- "@cosmjs/proto-signing": "^0.33.1",
+ "@cosmjs/proto-signing": "^0.36.2",
"@cosmjs/proto-signing-cjs": "npm:@cosmjs/proto-signing@~0.30.1",
- "@cosmjs/stargate": "^0.33.1",
+ "@cosmjs/stargate": "^0.36.2",
"@cosmjs/stargate-cjs": "npm:@cosmjs/stargate@~0.30.1",
- "@cosmjs/tendermint-rpc": "^0.33.1",
+ "@cosmjs/tendermint-rpc": "^0.36.2",
"@cosmjs/tendermint-rpc-cjs": "npm:@cosmjs/tendermint-rpc@~0.30.1",
- "@cosmjs/utils": "^0.33.1",
+ "@cosmjs/utils": "^0.36.2",
"@cosmjs/utils-cjs": "npm:@cosmjs/utils@~0.30.1",
"@stablelib/ed25519": "^2.0.2",
"@stablelib/ed25519-cjs": "npm:@stablelib/ed25519@^1.0.3",
"@types/secp256k1": "^4.0.6",
"@types/secp256k1-cjs": "npm:@types/secp256k1@^4.0.6",
- "cosmjs-types": "^0.9.0",
+ "cosmjs-types": "^0.10.1",
"cosmjs-types-cjs": "npm:cosmjs-types@^0.7.2",
"did-jwt": "^8.0.16",
"did-jwt-cjs": "npm:did-jwt@^8.0.15",
@@ -2930,7 +3189,7 @@
"secp256k1-cjs": "npm:secp256k1@^5.0.1",
"uint8arrays": "^5.1.0",
"uint8arrays-cjs": "npm:uint8arrays@^3.1.1",
- "uuid": "^11.1.0",
+ "uuid": "^13.0.0",
"uuid-cjs": "npm:uuid@~10.0.0"
},
"engines": {
@@ -2938,37 +3197,36 @@
}
},
"node_modules/@cheqd/sdk/node_modules/@cosmjs/amino": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.33.1.tgz",
- "integrity": "sha512-WfWiBf2EbIWpwKG9AOcsIIkR717SY+JdlXM/SL/bI66BdrhniAF+/ZNis9Vo9HF6lP2UU5XrSmFA4snAvEgdrg==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.36.2.tgz",
+ "integrity": "sha512-r4yV1bhl412gwHGlyaUaJHIJnmldtyGsAwyz3oHHVxduiECj06Rv6wqeyLZfQa9W6hU+MlZwy7LabSUkkyGwjA==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/crypto": "^0.33.1",
- "@cosmjs/encoding": "^0.33.1",
- "@cosmjs/math": "^0.33.1",
- "@cosmjs/utils": "^0.33.1"
+ "@cosmjs/crypto": "^0.36.2",
+ "@cosmjs/encoding": "^0.36.2",
+ "@cosmjs/math": "^0.36.2",
+ "@cosmjs/utils": "^0.36.2"
}
},
"node_modules/@cheqd/sdk/node_modules/@cosmjs/crypto": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.33.1.tgz",
- "integrity": "sha512-U4kGIj/SNBzlb2FGgA0sMR0MapVgJUg8N+oIAiN5+vl4GZ3aefmoL1RDyTrFS/7HrB+M+MtHsxC0tvEu4ic/zA==",
- "deprecated": "This uses elliptic for cryptographic operations, which contains several security-relevant bugs. To what degree this affects your application is something you need to carefully investigate. See https://github.com/cosmos/cosmjs/issues/1708 for further pointers. Starting with version 0.34.0 the cryptographic library has been replaced. However, private keys might still be at risk.",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.36.2.tgz",
+ "integrity": "sha512-QL4NHtcqR6DEKIN200aLeR8gKO433K0f5avKV0TVFP/g12UtnEGSk79PJq5Gv1PLc9GtATHgLLQI/3D8TEe+ig==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/encoding": "^0.33.1",
- "@cosmjs/math": "^0.33.1",
- "@cosmjs/utils": "^0.33.1",
- "@noble/hashes": "^1",
- "bn.js": "^5.2.0",
- "elliptic": "^6.6.1",
- "libsodium-wrappers-sumo": "^0.7.11"
+ "@cosmjs/encoding": "^0.36.2",
+ "@cosmjs/math": "^0.36.2",
+ "@cosmjs/utils": "^0.36.2",
+ "@noble/ciphers": "^1.3.0",
+ "@noble/curves": "^1.9.2",
+ "@noble/hashes": "^1.8.0",
+ "hash-wasm": "^4.12.0"
}
},
"node_modules/@cheqd/sdk/node_modules/@cosmjs/encoding": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.33.1.tgz",
- "integrity": "sha512-nuNxf29fUcQE14+1p//VVQDwd1iau5lhaW/7uMz7V2AH3GJbFJoJVaKvVyZvdFk+Cnu+s3wCqgq4gJkhRCJfKw==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.36.2.tgz",
+ "integrity": "sha512-i3+P1EKYoLcONAsmpJPhDAc3Wh3ajZNRHt/hczi/JEQXmleTJLVzv2mXUyllM6Qa+B6ybbr3Z2lnEFa8L3yLqg==",
"license": "Apache-2.0",
"dependencies": {
"base64-js": "^1.3.0",
@@ -2977,43 +3235,59 @@
}
},
"node_modules/@cheqd/sdk/node_modules/@cosmjs/math": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.33.1.tgz",
- "integrity": "sha512-ytGkWdKFCPiiBU5eqjHNd59djPpIsOjbr2CkNjlnI1Zmdj+HDkSoD9MUGpz9/RJvRir5IvsXqdE05x8EtoQkJA==",
- "license": "Apache-2.0",
- "dependencies": {
- "bn.js": "^5.2.0"
- }
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.36.2.tgz",
+ "integrity": "sha512-uJZRzxqnBk3MgxFgeyUwLgUzWkAIcmznWSB/tgGCjGCnUNebzI+44dA3ncEDCMqQysi/MZ+cSwAcDU7IY2PFeA==",
+ "license": "Apache-2.0"
},
"node_modules/@cheqd/sdk/node_modules/@cosmjs/proto-signing": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.33.1.tgz",
- "integrity": "sha512-Sv4W+MxX+0LVnd+2rU4Fw1HRsmMwSVSYULj7pRkij3wnPwUlTVoJjmKFgKz13ooIlfzPrz/dnNjGp/xnmXChFQ==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.36.2.tgz",
+ "integrity": "sha512-dyZsgZBQgGkaE4cazHVX8GDwrRJVKUVDnrODkyFXVNbxMnm4t6nxpK1qwgY9GHlWUhck3Dh9NT3BoMbXiMYTZQ==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/amino": "^0.33.1",
- "@cosmjs/crypto": "^0.33.1",
- "@cosmjs/encoding": "^0.33.1",
- "@cosmjs/math": "^0.33.1",
- "@cosmjs/utils": "^0.33.1",
- "cosmjs-types": "^0.9.0"
+ "@cosmjs/amino": "^0.36.2",
+ "@cosmjs/crypto": "^0.36.2",
+ "@cosmjs/encoding": "^0.36.2",
+ "@cosmjs/math": "^0.36.2",
+ "@cosmjs/utils": "^0.36.2",
+ "cosmjs-types": "^0.10.1"
}
},
"node_modules/@cheqd/sdk/node_modules/@cosmjs/utils": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.33.1.tgz",
- "integrity": "sha512-UnLHDY6KMmC+UXf3Ufyh+onE19xzEXjT4VZ504Acmk4PXxqyvG4cCPprlKUFnGUX7f0z8Or9MAOHXBx41uHBcg==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.36.2.tgz",
+ "integrity": "sha512-OOr2HU/Ph+/GI1Fx2UCf3LOyX9YTCP51d2HitTOjjEJRYnkfKXP3lMBl1FZo5QaFWxnfuBc+Cj+cSoiQUJRyzQ==",
"license": "Apache-2.0"
},
+ "node_modules/@cheqd/sdk/node_modules/cosmjs-types": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.10.1.tgz",
+ "integrity": "sha512-CENXb4O5GN+VyB68HYXFT2SOhv126Z59631rZC56m8uMWa6/cSlFeai8BwZGT1NMepw0Ecf+U8XSOnBzZUWh9Q==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@cheqd/sdk/node_modules/uuid": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
+ "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist-node/bin/uuid"
+ }
+ },
"node_modules/@cheqd/ts-proto": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/@cheqd/ts-proto/-/ts-proto-4.2.0.tgz",
- "integrity": "sha512-0/pKFSDtERs5euLW0mcry3Lr9mguDY3Sr+W9uzs7Iru6HEBxs+LjwcpaFr9073wlsKF9fLhsCDHvDJDwNxePkg==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@cheqd/ts-proto/-/ts-proto-4.2.1.tgz",
+ "integrity": "sha512-8O15Qaj/lyb/zNsKlUfP79XDnZw7lEToeONV8ji04AkFKf+hzPQNXhTMWp7Wf/vywUEzrHYZa1I4DITT6QmCJA==",
"license": "Apache-2.0",
"dependencies": {
"@bufbuild/protobuf": "^2.5.1",
"long": "^5.3.2",
- "protobufjs": "^7.5.3"
+ "protobufjs": "^8.0.0"
},
"engines": {
"node": ">=22.0.0"
@@ -3021,9 +3295,9 @@
},
"node_modules/@cheqd/ts-proto-cjs": {
"name": "@cheqd/ts-proto",
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/@cheqd/ts-proto/-/ts-proto-2.5.0.tgz",
- "integrity": "sha512-3KqyvcruFxvkz+p6LnSCyUnqBJ2bJeOnIDkaYoAMcmGcSNKti3VECOKGdjjEO3rG/0/gAR9bhEHu9j1mUKSFqA==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@cheqd/ts-proto/-/ts-proto-2.6.0.tgz",
+ "integrity": "sha512-0hbAFZzt4jvEQqCp0SjSM05f0l5HR4MhrWdlF4bk1jmHAz8U/FgCqXTBIJZ9nGG7RASX9t9MPbmhPOh6ED+4ow==",
"license": "Apache-2.0",
"dependencies": {
"@bufbuild/protobuf": "^2.2.2",
@@ -3034,6 +3308,30 @@
"node": ">=20"
}
},
+ "node_modules/@cheqd/ts-proto-cjs/node_modules/protobufjs": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz",
+ "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/@colors/colors": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
@@ -3236,12 +3534,12 @@
}
},
"node_modules/@cosmjs/json-rpc": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.33.1.tgz",
- "integrity": "sha512-T6VtWzecpmuTuMRGZWuBYHsMF/aznWCYUt/cGMWNSz7DBPipVd0w774PKpxXzpEbyt5sr61NiuLXc+Az15S/Cw==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.36.2.tgz",
+ "integrity": "sha512-3IRamylHVCxBevXGlnIoWUdJCLsP5LwHbXYUsBnC9T8UttZ5oYRN5gDf6+2dQEPk+p9xOv2i8xrCwNWxo7675Q==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/stream": "^0.33.1",
+ "@cosmjs/stream": "^0.36.2",
"xstream": "^11.14.0"
}
},
@@ -3391,31 +3689,31 @@
}
},
"node_modules/@cosmjs/socket": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.33.1.tgz",
- "integrity": "sha512-KzAeorten6Vn20sMiM6NNWfgc7jbyVo4Zmxev1FXa5EaoLCZy48cmT3hJxUJQvJP/lAy8wPGEjZ/u4rmF11x9A==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.36.2.tgz",
+ "integrity": "sha512-Pb7JcTFWnq6yfY0IEejHrpSxNDJYcqjjAa1D29a6b/obk4qa4o3oIV5bIx6zAbdRq8uLoBfvWs0bHTNnVuBWJg==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/stream": "^0.33.1",
+ "@cosmjs/stream": "^0.36.2",
"isomorphic-ws": "^4.0.1",
"ws": "^7",
"xstream": "^11.14.0"
}
},
"node_modules/@cosmjs/stargate": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.33.1.tgz",
- "integrity": "sha512-CnJ1zpSiaZgkvhk+9aTp5IPmgWn2uo+cNEBN8VuD9sD6BA0V4DMjqe251cNFLiMhkGtiE5I/WXFERbLPww3k8g==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.36.2.tgz",
+ "integrity": "sha512-vnNK4dXF+s2v1aKPfYxKVrvXPcnBQb8rPoBScnTpPWnRt3XXbLw7Oo6fTQQWwKYNKQzi6DOApeEB+bCYcaPAAw==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/amino": "^0.33.1",
- "@cosmjs/encoding": "^0.33.1",
- "@cosmjs/math": "^0.33.1",
- "@cosmjs/proto-signing": "^0.33.1",
- "@cosmjs/stream": "^0.33.1",
- "@cosmjs/tendermint-rpc": "^0.33.1",
- "@cosmjs/utils": "^0.33.1",
- "cosmjs-types": "^0.9.0"
+ "@cosmjs/amino": "^0.36.2",
+ "@cosmjs/encoding": "^0.36.2",
+ "@cosmjs/math": "^0.36.2",
+ "@cosmjs/proto-signing": "^0.36.2",
+ "@cosmjs/stream": "^0.36.2",
+ "@cosmjs/tendermint-rpc": "^0.36.2",
+ "@cosmjs/utils": "^0.36.2",
+ "cosmjs-types": "^0.10.1"
}
},
"node_modules/@cosmjs/stargate-cjs": {
@@ -3609,37 +3907,36 @@
}
},
"node_modules/@cosmjs/stargate/node_modules/@cosmjs/amino": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.33.1.tgz",
- "integrity": "sha512-WfWiBf2EbIWpwKG9AOcsIIkR717SY+JdlXM/SL/bI66BdrhniAF+/ZNis9Vo9HF6lP2UU5XrSmFA4snAvEgdrg==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.36.2.tgz",
+ "integrity": "sha512-r4yV1bhl412gwHGlyaUaJHIJnmldtyGsAwyz3oHHVxduiECj06Rv6wqeyLZfQa9W6hU+MlZwy7LabSUkkyGwjA==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/crypto": "^0.33.1",
- "@cosmjs/encoding": "^0.33.1",
- "@cosmjs/math": "^0.33.1",
- "@cosmjs/utils": "^0.33.1"
+ "@cosmjs/crypto": "^0.36.2",
+ "@cosmjs/encoding": "^0.36.2",
+ "@cosmjs/math": "^0.36.2",
+ "@cosmjs/utils": "^0.36.2"
}
},
"node_modules/@cosmjs/stargate/node_modules/@cosmjs/crypto": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.33.1.tgz",
- "integrity": "sha512-U4kGIj/SNBzlb2FGgA0sMR0MapVgJUg8N+oIAiN5+vl4GZ3aefmoL1RDyTrFS/7HrB+M+MtHsxC0tvEu4ic/zA==",
- "deprecated": "This uses elliptic for cryptographic operations, which contains several security-relevant bugs. To what degree this affects your application is something you need to carefully investigate. See https://github.com/cosmos/cosmjs/issues/1708 for further pointers. Starting with version 0.34.0 the cryptographic library has been replaced. However, private keys might still be at risk.",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.36.2.tgz",
+ "integrity": "sha512-QL4NHtcqR6DEKIN200aLeR8gKO433K0f5avKV0TVFP/g12UtnEGSk79PJq5Gv1PLc9GtATHgLLQI/3D8TEe+ig==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/encoding": "^0.33.1",
- "@cosmjs/math": "^0.33.1",
- "@cosmjs/utils": "^0.33.1",
- "@noble/hashes": "^1",
- "bn.js": "^5.2.0",
- "elliptic": "^6.6.1",
- "libsodium-wrappers-sumo": "^0.7.11"
+ "@cosmjs/encoding": "^0.36.2",
+ "@cosmjs/math": "^0.36.2",
+ "@cosmjs/utils": "^0.36.2",
+ "@noble/ciphers": "^1.3.0",
+ "@noble/curves": "^1.9.2",
+ "@noble/hashes": "^1.8.0",
+ "hash-wasm": "^4.12.0"
}
},
"node_modules/@cosmjs/stargate/node_modules/@cosmjs/encoding": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.33.1.tgz",
- "integrity": "sha512-nuNxf29fUcQE14+1p//VVQDwd1iau5lhaW/7uMz7V2AH3GJbFJoJVaKvVyZvdFk+Cnu+s3wCqgq4gJkhRCJfKw==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.36.2.tgz",
+ "integrity": "sha512-i3+P1EKYoLcONAsmpJPhDAc3Wh3ajZNRHt/hczi/JEQXmleTJLVzv2mXUyllM6Qa+B6ybbr3Z2lnEFa8L3yLqg==",
"license": "Apache-2.0",
"dependencies": {
"base64-js": "^1.3.0",
@@ -3648,57 +3945,59 @@
}
},
"node_modules/@cosmjs/stargate/node_modules/@cosmjs/math": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.33.1.tgz",
- "integrity": "sha512-ytGkWdKFCPiiBU5eqjHNd59djPpIsOjbr2CkNjlnI1Zmdj+HDkSoD9MUGpz9/RJvRir5IvsXqdE05x8EtoQkJA==",
- "license": "Apache-2.0",
- "dependencies": {
- "bn.js": "^5.2.0"
- }
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.36.2.tgz",
+ "integrity": "sha512-uJZRzxqnBk3MgxFgeyUwLgUzWkAIcmznWSB/tgGCjGCnUNebzI+44dA3ncEDCMqQysi/MZ+cSwAcDU7IY2PFeA==",
+ "license": "Apache-2.0"
},
"node_modules/@cosmjs/stargate/node_modules/@cosmjs/proto-signing": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.33.1.tgz",
- "integrity": "sha512-Sv4W+MxX+0LVnd+2rU4Fw1HRsmMwSVSYULj7pRkij3wnPwUlTVoJjmKFgKz13ooIlfzPrz/dnNjGp/xnmXChFQ==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.36.2.tgz",
+ "integrity": "sha512-dyZsgZBQgGkaE4cazHVX8GDwrRJVKUVDnrODkyFXVNbxMnm4t6nxpK1qwgY9GHlWUhck3Dh9NT3BoMbXiMYTZQ==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/amino": "^0.33.1",
- "@cosmjs/crypto": "^0.33.1",
- "@cosmjs/encoding": "^0.33.1",
- "@cosmjs/math": "^0.33.1",
- "@cosmjs/utils": "^0.33.1",
- "cosmjs-types": "^0.9.0"
+ "@cosmjs/amino": "^0.36.2",
+ "@cosmjs/crypto": "^0.36.2",
+ "@cosmjs/encoding": "^0.36.2",
+ "@cosmjs/math": "^0.36.2",
+ "@cosmjs/utils": "^0.36.2",
+ "cosmjs-types": "^0.10.1"
}
},
"node_modules/@cosmjs/stargate/node_modules/@cosmjs/utils": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.33.1.tgz",
- "integrity": "sha512-UnLHDY6KMmC+UXf3Ufyh+onE19xzEXjT4VZ504Acmk4PXxqyvG4cCPprlKUFnGUX7f0z8Or9MAOHXBx41uHBcg==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.36.2.tgz",
+ "integrity": "sha512-OOr2HU/Ph+/GI1Fx2UCf3LOyX9YTCP51d2HitTOjjEJRYnkfKXP3lMBl1FZo5QaFWxnfuBc+Cj+cSoiQUJRyzQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@cosmjs/stargate/node_modules/cosmjs-types": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.10.1.tgz",
+ "integrity": "sha512-CENXb4O5GN+VyB68HYXFT2SOhv126Z59631rZC56m8uMWa6/cSlFeai8BwZGT1NMepw0Ecf+U8XSOnBzZUWh9Q==",
"license": "Apache-2.0"
},
"node_modules/@cosmjs/stream": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.33.1.tgz",
- "integrity": "sha512-bMUvEENjeQPSTx+YRzVsWT1uFIdHRcf4brsc14SOoRQ/j5rOJM/aHfsf/BmdSAnYbdOQ3CMKj/8nGAQ7xUdn7w==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.36.2.tgz",
+ "integrity": "sha512-FlZx2Buovem837LdTLPkPFcxzuQ7zierAqSXwMPr/MG3k+qMxHNfLFTTCXMNWQ4ZlbYedud8ZqCL3/HKdS5mig==",
"license": "Apache-2.0",
"dependencies": {
"xstream": "^11.14.0"
}
},
"node_modules/@cosmjs/tendermint-rpc": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.33.1.tgz",
- "integrity": "sha512-22klDFq2MWnf//C8+rZ5/dYatr6jeGT+BmVbutXYfAK9fmODbtFcumyvB6uWaEORWfNukl8YK1OLuaWezoQvxA==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.36.2.tgz",
+ "integrity": "sha512-76Z99C1NVf/Yv/1bWU0wul8MhRwVdqiZxqU5bcHqvJLoQ2nKUfGpSSYRdbMHfZ63J8ryRqQ95uPvPTfrBb+agw==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/crypto": "^0.33.1",
- "@cosmjs/encoding": "^0.33.1",
- "@cosmjs/json-rpc": "^0.33.1",
- "@cosmjs/math": "^0.33.1",
- "@cosmjs/socket": "^0.33.1",
- "@cosmjs/stream": "^0.33.1",
- "@cosmjs/utils": "^0.33.1",
- "axios": "^1.6.0",
+ "@cosmjs/crypto": "^0.36.2",
+ "@cosmjs/encoding": "^0.36.2",
+ "@cosmjs/json-rpc": "^0.36.2",
+ "@cosmjs/math": "^0.36.2",
+ "@cosmjs/socket": "^0.36.2",
+ "@cosmjs/stream": "^0.36.2",
+ "@cosmjs/utils": "^0.36.2",
"readonly-date": "^1.0.0",
"xstream": "^11.14.0"
}
@@ -3805,25 +4104,24 @@
}
},
"node_modules/@cosmjs/tendermint-rpc/node_modules/@cosmjs/crypto": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.33.1.tgz",
- "integrity": "sha512-U4kGIj/SNBzlb2FGgA0sMR0MapVgJUg8N+oIAiN5+vl4GZ3aefmoL1RDyTrFS/7HrB+M+MtHsxC0tvEu4ic/zA==",
- "deprecated": "This uses elliptic for cryptographic operations, which contains several security-relevant bugs. To what degree this affects your application is something you need to carefully investigate. See https://github.com/cosmos/cosmjs/issues/1708 for further pointers. Starting with version 0.34.0 the cryptographic library has been replaced. However, private keys might still be at risk.",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.36.2.tgz",
+ "integrity": "sha512-QL4NHtcqR6DEKIN200aLeR8gKO433K0f5avKV0TVFP/g12UtnEGSk79PJq5Gv1PLc9GtATHgLLQI/3D8TEe+ig==",
"license": "Apache-2.0",
"dependencies": {
- "@cosmjs/encoding": "^0.33.1",
- "@cosmjs/math": "^0.33.1",
- "@cosmjs/utils": "^0.33.1",
- "@noble/hashes": "^1",
- "bn.js": "^5.2.0",
- "elliptic": "^6.6.1",
- "libsodium-wrappers-sumo": "^0.7.11"
+ "@cosmjs/encoding": "^0.36.2",
+ "@cosmjs/math": "^0.36.2",
+ "@cosmjs/utils": "^0.36.2",
+ "@noble/ciphers": "^1.3.0",
+ "@noble/curves": "^1.9.2",
+ "@noble/hashes": "^1.8.0",
+ "hash-wasm": "^4.12.0"
}
},
"node_modules/@cosmjs/tendermint-rpc/node_modules/@cosmjs/encoding": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.33.1.tgz",
- "integrity": "sha512-nuNxf29fUcQE14+1p//VVQDwd1iau5lhaW/7uMz7V2AH3GJbFJoJVaKvVyZvdFk+Cnu+s3wCqgq4gJkhRCJfKw==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.36.2.tgz",
+ "integrity": "sha512-i3+P1EKYoLcONAsmpJPhDAc3Wh3ajZNRHt/hczi/JEQXmleTJLVzv2mXUyllM6Qa+B6ybbr3Z2lnEFa8L3yLqg==",
"license": "Apache-2.0",
"dependencies": {
"base64-js": "^1.3.0",
@@ -3832,31 +4130,17 @@
}
},
"node_modules/@cosmjs/tendermint-rpc/node_modules/@cosmjs/math": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.33.1.tgz",
- "integrity": "sha512-ytGkWdKFCPiiBU5eqjHNd59djPpIsOjbr2CkNjlnI1Zmdj+HDkSoD9MUGpz9/RJvRir5IvsXqdE05x8EtoQkJA==",
- "license": "Apache-2.0",
- "dependencies": {
- "bn.js": "^5.2.0"
- }
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.36.2.tgz",
+ "integrity": "sha512-uJZRzxqnBk3MgxFgeyUwLgUzWkAIcmznWSB/tgGCjGCnUNebzI+44dA3ncEDCMqQysi/MZ+cSwAcDU7IY2PFeA==",
+ "license": "Apache-2.0"
},
"node_modules/@cosmjs/tendermint-rpc/node_modules/@cosmjs/utils": {
- "version": "0.33.1",
- "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.33.1.tgz",
- "integrity": "sha512-UnLHDY6KMmC+UXf3Ufyh+onE19xzEXjT4VZ504Acmk4PXxqyvG4cCPprlKUFnGUX7f0z8Or9MAOHXBx41uHBcg==",
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.36.2.tgz",
+ "integrity": "sha512-OOr2HU/Ph+/GI1Fx2UCf3LOyX9YTCP51d2HitTOjjEJRYnkfKXP3lMBl1FZo5QaFWxnfuBc+Cj+cSoiQUJRyzQ==",
"license": "Apache-2.0"
},
- "node_modules/@cosmjs/tendermint-rpc/node_modules/axios": {
- "version": "1.13.5",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
- "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
- "license": "MIT",
- "dependencies": {
- "follow-redirects": "^1.15.11",
- "form-data": "^4.0.5",
- "proxy-from-env": "^1.1.0"
- }
- },
"node_modules/@cosmjs/utils": {
"version": "0.32.4",
"resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.32.4.tgz",
@@ -4319,20 +4603,20 @@
}
},
"node_modules/@docknetwork/cheqd-blockchain-api": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@docknetwork/cheqd-blockchain-api/-/cheqd-blockchain-api-4.0.5.tgz",
- "integrity": "sha512-frmo7jDk/NS9RlcuXBRD7tGieDEVgdRvTUsTIPZ0/AEyZWsM0eNEGSmxsTtwyh3Wi9Nra+g4lB5tl9PxyeQSZQ==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@docknetwork/cheqd-blockchain-api/-/cheqd-blockchain-api-4.1.1.tgz",
+ "integrity": "sha512-I1YsexfImHltf27x+p54hIMED2a3y+rprJgPmQeqrPt2mGQstjTVZUQLcetxyYmWqpt11L/RUefVGcSJSm1UIQ==",
"license": "MIT",
"dependencies": {
- "@cheqd/sdk": "5.3.2",
- "@cheqd/ts-proto": "^4.1.0",
+ "@cheqd/sdk": "5.4.3",
+ "@cheqd/ts-proto": "^4.2.0",
"p-limit": "^6.1.0"
},
"engines": {
"node": ">=22.0.0"
},
"peerDependencies": {
- "@docknetwork/credential-sdk": "^0.54.6"
+ "@docknetwork/credential-sdk": "^0.54.11"
}
},
"node_modules/@docknetwork/cheqd-blockchain-api/node_modules/p-limit": {
@@ -4363,26 +4647,29 @@
}
},
"node_modules/@docknetwork/cheqd-blockchain-modules": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/@docknetwork/cheqd-blockchain-modules/-/cheqd-blockchain-modules-4.0.6.tgz",
- "integrity": "sha512-flHN0YTBUUUfXx6ZjP7RFKu2VrpnIfbNOzyZiMNVuESuGIS3mdp0TOsiCkY2bkd2DGipHaQYwxpyLesU3L0jZg==",
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/@docknetwork/cheqd-blockchain-modules/-/cheqd-blockchain-modules-4.0.8.tgz",
+ "integrity": "sha512-c/fO+Ar9nMgbB0+ME3mDRvWaFkvrcuLRQerA04NxpRLXKgq2Jth0r9pzRSJWiHM6bDmM0qdeXS7BSVq+iY0K9g==",
"license": "MIT",
"engines": {
"node": ">=22.0.0"
},
"peerDependencies": {
- "@docknetwork/credential-sdk": "^0.54.9"
+ "@docknetwork/credential-sdk": "^0.54.11"
}
},
"node_modules/@docknetwork/credential-sdk": {
- "version": "0.54.9",
- "resolved": "https://registry.npmjs.org/@docknetwork/credential-sdk/-/credential-sdk-0.54.9.tgz",
- "integrity": "sha512-Sq7mxjDpF5KCmQYlZqSIVPVgYFRdyd3JR0nqcHfocnzeeeahuHFT0APfXff3JXpd+QTjVPhkNHLNCDZo/+B8jQ==",
+ "version": "0.54.16",
+ "resolved": "https://registry.npmjs.org/@docknetwork/credential-sdk/-/credential-sdk-0.54.16.tgz",
+ "integrity": "sha512-A+EcOssWCvHYtmLwWdWIsQlRXI0tLJx2ZezZH8zWF/bpERIJCka/hRMy8OQwBfPoOMOTz8Og/HgGnLkD/mlZ4g==",
"license": "MIT",
"dependencies": {
+ "@astronautlabs/jsonpath": "^1.1.2",
"@digitalcredentials/vc-status-list": "^9.0.0",
"@docknetwork/crypto-wasm-ts": "^0.63.0",
+ "@docknetwork/vc-delegation-engine": "1.0.3",
"@juanelas/base64": "^1.1.5",
+ "@sphereon/pex": "^5.0.0-unstable.28",
"@sphereon/ssi-sdk-ext.did-resolver-jwk": "^0.26.0",
"@stablelib/ed25519": "^1.0.0",
"@transmute/json-web-signature": "^0.7.0-unstable.82",
@@ -4411,6 +4698,97 @@
"node": ">=22.0.0"
}
},
+ "node_modules/@docknetwork/credential-sdk/node_modules/@sd-jwt/decode": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/@sd-jwt/decode/-/decode-0.7.2.tgz",
+ "integrity": "sha512-dan2LSvK63SKwb62031G4r7TE4TaiI0EK1KbPXqS+LCXNkNDUHqhtYp9uOpj+grXceCsMtMa2f8VnUfsjmwHHg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@sd-jwt/types": "0.7.2",
+ "@sd-jwt/utils": "0.7.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@docknetwork/credential-sdk/node_modules/@sd-jwt/present": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/@sd-jwt/present/-/present-0.7.2.tgz",
+ "integrity": "sha512-mQV85u2+mLLy2VZ9Wx2zpaB6yTDnbhCfWkP7eeCrzJQHBKAAHko8GrylEFmLKewFIcajS/r4lT/zHOsCkp5pZw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@sd-jwt/decode": "0.7.2",
+ "@sd-jwt/types": "0.7.2",
+ "@sd-jwt/utils": "0.7.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@docknetwork/credential-sdk/node_modules/@sd-jwt/types": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/@sd-jwt/types/-/types-0.7.2.tgz",
+ "integrity": "sha512-1NRKowiW0ZiB9SGLApLPBH4Xk8gDQJ+nA9NdZ+uy6MmJKLEwjuJxO7yTvRIv/jX/0/Ebh339S7Kq4RD2AiFuRg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@docknetwork/credential-sdk/node_modules/@sd-jwt/utils": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/@sd-jwt/utils/-/utils-0.7.2.tgz",
+ "integrity": "sha512-aMPY7uHRMgyI5PlDvEiIc+eBFGC1EM8OCQRiEjJ8HGN0pajWMYj0qwSw7pS90A49/DsYU1a5Zpvb7nyjgGH0Yg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@sd-jwt/types": "0.7.2",
+ "js-base64": "^3.7.6"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@docknetwork/credential-sdk/node_modules/@sphereon/pex": {
+ "version": "5.0.0-unstable.28",
+ "resolved": "https://registry.npmjs.org/@sphereon/pex/-/pex-5.0.0-unstable.28.tgz",
+ "integrity": "sha512-zxHCWAc7fKppS7XX0zxnI4TF+Rdjax8pHc3exrYzn3t59dlv5siEAeYdtFrWJT4UVB5wTGzIEufzV5r+tfjelg==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@astronautlabs/jsonpath": "^1.1.2",
+ "@sd-jwt/decode": "^0.7.2",
+ "@sd-jwt/present": "^0.7.2",
+ "@sd-jwt/types": "^0.7.2",
+ "@sphereon/pex-models": "^2.3.1",
+ "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.366",
+ "ajv": "^8.12.0",
+ "ajv-formats": "^2.1.1",
+ "jwt-decode": "^3.1.2",
+ "nanoid": "^3.3.7",
+ "uint8arrays": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@docknetwork/credential-sdk/node_modules/@sphereon/pex-models": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/@sphereon/pex-models/-/pex-models-2.3.2.tgz",
+ "integrity": "sha512-foFxfLkRwcn/MOp/eht46Q7wsvpQGlO7aowowIIb5Tz9u97kYZ2kz6K2h2ODxWuv5CRA7Q0MY8XUBGE2lfOhOQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@docknetwork/credential-sdk/node_modules/@sphereon/ssi-types": {
+ "version": "0.30.2-feature.mdoc.funke2.366",
+ "resolved": "https://registry.npmjs.org/@sphereon/ssi-types/-/ssi-types-0.30.2-feature.mdoc.funke2.366.tgz",
+ "integrity": "sha512-PmfTIbBovxdg7d9RD4WTVsJQtIMk5kcZo5qrBpumyPqz4TFiuGIjjuen0tDtv/IAwXSiNXX51MOHGfssQLskZA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@sd-jwt/decode": "^0.7.2",
+ "@sphereon/kmp-mdoc-core": "0.2.0-SNAPSHOT.10",
+ "debug": "^4.3.5",
+ "events": "^3.3.0",
+ "jwt-decode": "^3.1.2"
+ }
+ },
"node_modules/@docknetwork/credential-sdk/node_modules/@stablelib/ed25519": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-1.0.3.tgz",
@@ -4449,12 +4827,44 @@
"@stablelib/wipe": "^1.0.1"
}
},
+ "node_modules/@docknetwork/credential-sdk/node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@docknetwork/credential-sdk/node_modules/jwt-decode": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+ "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==",
+ "license": "MIT"
+ },
"node_modules/@docknetwork/credential-sdk/node_modules/multiformats": {
"version": "9.9.0",
"resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz",
"integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==",
"license": "(Apache-2.0 AND MIT)"
},
+ "node_modules/@docknetwork/credential-sdk/node_modules/uint8arrays": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz",
+ "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==",
+ "license": "MIT",
+ "dependencies": {
+ "multiformats": "^9.4.2"
+ }
+ },
"node_modules/@docknetwork/credential-sdk/node_modules/uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
@@ -4511,13 +4921,28 @@
"@digitalbazaar/edv-client": "^11.3.2"
}
},
+ "node_modules/@docknetwork/vc-delegation-engine": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@docknetwork/vc-delegation-engine/-/vc-delegation-engine-1.0.3.tgz",
+ "integrity": "sha512-cOSHvPd5z/UlYyYj5P+WMIEqTnZNU0Wv/sXrmg+45K8P4uq7gNgBwMvVpoOjGe/KonFheMSBhFHd51MXIeMl5w==",
+ "license": "ISC",
+ "dependencies": {
+ "base64url": "^3.0.1",
+ "jsonld": "^6.0.0",
+ "jsonpath-plus": "^10.1.0",
+ "rify": "^0.7.1"
+ },
+ "peerDependencies": {
+ "@cedar-policy/cedar-wasm": "^4.5.0"
+ }
+ },
"node_modules/@docknetwork/wallet-sdk-core": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/@docknetwork/wallet-sdk-core/-/wallet-sdk-core-1.7.0.tgz",
- "integrity": "sha512-GFq14g0pLq1vUxI9AEKvj1QJMPoXyGHKS1eRsJsvSjbaPjoGZuQqJaHQ17ZD1bcs8EZgryhCcT28rRMZ04Lp/Q==",
+ "version": "1.7.6",
+ "resolved": "https://registry.npmjs.org/@docknetwork/wallet-sdk-core/-/wallet-sdk-core-1.7.6.tgz",
+ "integrity": "sha512-jk+5oikQFj2PPdQcNbschBaD8j8UnFR/u17hRVaJYc/+g99JPOeJmluEAeZvBNwgVFCGUm16cmg9JESqpvSudA==",
"license": "https://github.com/docknetwork/wallet-sdk/LICENSE",
"dependencies": {
- "@docknetwork/wallet-sdk-wasm": "^1.5.14",
+ "@docknetwork/wallet-sdk-wasm": "^1.7.6",
"futoin-hkdf": "^1.5.3"
},
"peerDependencies": {
@@ -4528,13 +4953,12 @@
}
},
"node_modules/@docknetwork/wallet-sdk-data-store": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/@docknetwork/wallet-sdk-data-store/-/wallet-sdk-data-store-1.7.0.tgz",
- "integrity": "sha512-39rF8Ix+aa3M+qh/oKNjRJ+7uf6zTygWzHaagLF02VbZq8c4Lxd50OhiA+7VY25cqFUD/08EbiF7msL7/qNV2A==",
+ "version": "1.7.6",
+ "resolved": "https://registry.npmjs.org/@docknetwork/wallet-sdk-data-store/-/wallet-sdk-data-store-1.7.6.tgz",
+ "integrity": "sha512-Bps19PIqEmFxwFgqaE65e8yHQz599AiQcVauBQyydYSNkYS/ftErQ0L5wxLoZKWIzbHwxFyvSPbe1d6dffTItg==",
"license": "https://github.com/docknetwork/wallet-sdk/LICENSE",
- "peer": true,
"dependencies": {
- "@docknetwork/wallet-sdk-wasm": "^1.7.0",
+ "@docknetwork/wallet-sdk-wasm": "^1.7.6",
"uuid": "^8.3.2"
},
"peerDependencies": {
@@ -4542,12 +4966,12 @@
}
},
"node_modules/@docknetwork/wallet-sdk-data-store-web": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/@docknetwork/wallet-sdk-data-store-web/-/wallet-sdk-data-store-web-1.7.0.tgz",
- "integrity": "sha512-8Xdhz3+qikdOvKbG+JAPDOFZgqvqGzKqqVxDb8u0uDkrOsrW2MWAWsnxqJziKDEGmrLbGcq8NC1KDTNlM3CfEg==",
+ "version": "1.7.6",
+ "resolved": "https://registry.npmjs.org/@docknetwork/wallet-sdk-data-store-web/-/wallet-sdk-data-store-web-1.7.6.tgz",
+ "integrity": "sha512-p4IAKTUbfmPAJTpkI11PIJ+wKEgBsKG4oDvrEMmOqp8Jqjtxh5avqkA50a+TBcpW9jFa1QKYiN62l8RFNV8Uug==",
"license": "https://github.com/docknetwork/wallet-sdk/LICENSE",
"dependencies": {
- "@docknetwork/wallet-sdk-wasm": "^1.7.0",
+ "@docknetwork/wallet-sdk-wasm": "^1.7.6",
"uuid": "^8.3.2"
},
"peerDependencies": {
@@ -4568,15 +4992,14 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"license": "MIT",
- "peer": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@docknetwork/wallet-sdk-dids": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/@docknetwork/wallet-sdk-dids/-/wallet-sdk-dids-1.7.0.tgz",
- "integrity": "sha512-x4/3xja7Ubog4rcpY1jH4T/UW8pV+iWyPLy4kX0ZZNoL1lOpvIPwe2Ys982//gAeytiWSLEuvqCKiuuCVkMYPg==",
+ "version": "1.7.6",
+ "resolved": "https://registry.npmjs.org/@docknetwork/wallet-sdk-dids/-/wallet-sdk-dids-1.7.6.tgz",
+ "integrity": "sha512-Lvv5zvmEJISHJLmBNkNnrQ6ylc8WVZzBfJQEEjy1KuvT7eHhmtcvvZ5d5hgP1eVPONt+I+7BIbvMCJ/hrrmDaQ==",
"license": "https://github.com/docknetwork/wallet-sdk/LICENSE",
"dependencies": {
"@digitalbazaar/did-method-key": "^2.0.0",
@@ -4593,18 +5016,20 @@
}
},
"node_modules/@docknetwork/wallet-sdk-wasm": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/@docknetwork/wallet-sdk-wasm/-/wallet-sdk-wasm-1.7.0.tgz",
- "integrity": "sha512-XYfaqIMa50tQqD1iqmExk1Ra8IeJAaA293hUUButmOMkGDf55cwGAuogd5jJeTTMWyWSFx5phHtnayDhrMlGXA==",
+ "version": "1.7.6",
+ "resolved": "https://registry.npmjs.org/@docknetwork/wallet-sdk-wasm/-/wallet-sdk-wasm-1.7.6.tgz",
+ "integrity": "sha512-vf7+RW+m9B0rHk3U8x5EnFu9rgqK40A7s1/16KRHkR9KLPyn3fx591rR+5pFQpzLCfpXmI53v9VrS4vombmSCw==",
"license": "https://github.com/docknetwork/wallet-sdk/LICENSE",
"dependencies": {
"@astronautlabs/jsonpath": "^1.1.2",
+ "@cedar-policy/cedar-wasm": "^4.5.0",
"@cosmjs/proto-signing": "^0.32.4",
- "@docknetwork/cheqd-blockchain-api": "4.0.5",
- "@docknetwork/cheqd-blockchain-modules": "4.0.6",
- "@docknetwork/credential-sdk": "0.54.9",
+ "@docknetwork/cheqd-blockchain-api": "4.1.1",
+ "@docknetwork/cheqd-blockchain-modules": "4.0.8",
+ "@docknetwork/credential-sdk": "0.54.16",
"@docknetwork/universal-wallet": "^2.0.1",
- "@docknetwork/wallet-sdk-dids": "^1.7.0",
+ "@docknetwork/vc-delegation-engine": "1.0.3",
+ "@docknetwork/wallet-sdk-dids": "^1.7.6",
"@noble/hashes": "1.8.0",
"@scure/bip39": "^1.6.0",
"@sd-jwt/crypto-nodejs": "^0.15.0",
@@ -4616,7 +5041,9 @@
"axios-retry": "^3.2.5",
"base64url": "^3.0.1",
"cwait": "1.1.2",
+ "futoin-hkdf": "^1.5.3",
"json-rpc-2.0": "^0.2.16",
+ "jsonld": "^6.0.0",
"p-limit": "2.3.0",
"uuid": "^8.3.2",
"winston": "^3.3.3"
@@ -5325,9 +5752,9 @@
}
},
"node_modules/@hono/node-server": {
- "version": "1.19.12",
- "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.12.tgz",
- "integrity": "sha512-txsUW4SQ1iilgE0l9/e9VQWmELXifEFvmdA1j6WFh/aFPj99hIntrSsq/if0UWyGVkmrRPKA1wCeP+UCr1B9Uw==",
+ "version": "1.19.13",
+ "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.13.tgz",
+ "integrity": "sha512-TsQLe4i2gvoTtrHje625ngThGBySOgSK3Xo2XRYOdqGN1teR8+I7vchQC46uLJi8OF62YTYA3AhSpumtkhsaKQ==",
"license": "MIT",
"engines": {
"node": ">=18.14.1"
@@ -5876,6 +6303,30 @@
"@js-joda/core": ">=1.11.0"
}
},
+ "node_modules/@jsep-plugin/assignment": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz",
+ "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.16.0"
+ },
+ "peerDependencies": {
+ "jsep": "^0.4.0||^1.0.0"
+ }
+ },
+ "node_modules/@jsep-plugin/regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz",
+ "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.16.0"
+ },
+ "peerDependencies": {
+ "jsep": "^0.4.0||^1.0.0"
+ }
+ },
"node_modules/@juanelas/base64": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@juanelas/base64/-/base64-1.1.5.tgz",
@@ -6693,6 +7144,16 @@
"format-util": "^1.0.5"
}
},
+ "node_modules/@sphereon/kmp-mdoc-core": {
+ "version": "0.2.0-SNAPSHOT.10",
+ "resolved": "https://registry.npmjs.org/@sphereon/kmp-mdoc-core/-/kmp-mdoc-core-0.2.0-SNAPSHOT.10.tgz",
+ "integrity": "sha512-mHH7I6fWdztaNjguGJOLaerXWnQymQ/xKQ8NqClIXoI2PJNgmpQG6DxFcLRs1aYyWg1iY8bPliLJi41u94KdCA==",
+ "dependencies": {
+ "@js-joda/core": "5.6.3",
+ "@js-joda/timezone": "2.3.0",
+ "format-util": "^1.0.5"
+ }
+ },
"node_modules/@sphereon/oid4vc-common": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@sphereon/oid4vc-common/-/oid4vc-common-0.16.0.tgz",
@@ -7076,9 +7537,9 @@
"license": "MIT"
},
"node_modules/@stablelib/ed25519": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-2.0.2.tgz",
- "integrity": "sha512-d/lJ5sgzhtmpMIbKFWfev+i6WebBdIzzBpMzXtZdvUijoksjXosYFNqytoMj7cRshNj+/XTLYnnVMdZfd+penw==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-2.1.0.tgz",
+ "integrity": "sha512-8GLWoJur9nJiErABKHs5MjceSiYJJ2n8QP9k8Q5x6GWU2y5oAQ6qzPh8kCgQy5aHlUxcmRA1frQ5Gu2bHoIDPw==",
"license": "MIT",
"dependencies": {
"@stablelib/random": "^2.0.1",
@@ -7669,9 +8130,9 @@
"license": "MIT"
},
"node_modules/@types/lodash": {
- "version": "4.17.23",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.23.tgz",
- "integrity": "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==",
+ "version": "4.17.24",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz",
+ "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
"license": "MIT"
},
"node_modules/@types/long": {
@@ -8150,6 +8611,13 @@
"url": "https://opencollective.com/vitest"
}
},
+ "node_modules/@yarnpkg/lockfile": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
+ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -8444,12 +8912,6 @@
"node": ">= 0.4"
}
},
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "license": "MIT"
- },
"node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
@@ -8495,9 +8957,9 @@
}
},
"node_modules/b4a": {
- "version": "1.7.5",
- "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.5.tgz",
- "integrity": "sha512-iEsKNwDh1wiWTps1/hdkNdmBgDlDVZP5U57ZVOlt+dNFqpc/lpPouCIxZw+DYBgc4P9NDfIZMPNR4CHNhzwLIA==",
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz",
+ "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==",
"license": "Apache-2.0",
"peerDependencies": {
"react-native-b4a": "*"
@@ -9390,18 +9852,6 @@
"node": ">=12.20"
}
},
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "license": "MIT",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
@@ -9897,15 +10347,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -10216,9 +10657,9 @@
}
},
"node_modules/es-abstract": {
- "version": "1.24.1",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
- "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==",
+ "version": "1.24.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz",
+ "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==",
"license": "MIT",
"dependencies": {
"array-buffer-byte-length": "^1.0.2",
@@ -11212,9 +11653,9 @@
}
},
"node_modules/file-type": {
- "version": "21.3.0",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.0.tgz",
- "integrity": "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==",
+ "version": "21.3.4",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.4.tgz",
+ "integrity": "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==",
"license": "MIT",
"dependencies": {
"@tokenizer/inflate": "^0.4.1",
@@ -11339,6 +11780,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/find-yarn-workspace-root": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
+ "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "micromatch": "^4.0.2"
+ }
+ },
"node_modules/flat": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
@@ -11433,43 +11884,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/form-data": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
- "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
- "license": "MIT",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "es-set-tostringtag": "^2.1.0",
- "hasown": "^2.0.2",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/form-data/node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/form-data/node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/format-util": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.5.tgz",
@@ -12022,6 +12436,12 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
+ "node_modules/hash-wasm": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.12.0.tgz",
+ "integrity": "sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ==",
+ "license": "MIT"
+ },
"node_modules/hash.js": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
@@ -12056,9 +12476,9 @@
}
},
"node_modules/hono": {
- "version": "4.12.11",
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.11.tgz",
- "integrity": "sha512-r4xbIa3mGGGoH9nN4A14DOg2wx7y2oQyJEb5O57C/xzETG/qx4c7CVDQ5WMeKHZ7ORk2W0hZ/sQKXTav3cmYBA==",
+ "version": "4.12.12",
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.12.tgz",
+ "integrity": "sha512-p1JfQMKaceuCbpJKAPKVqyqviZdS0eUxH9v82oWo1kb9xjQ5wA6iP3FNVAPDFlz5/p7d45lO+BpSk1tuSZMF4Q==",
"license": "MIT",
"engines": {
"node": ">=16.9.0"
@@ -12413,6 +12833,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -12705,6 +13141,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
@@ -13637,6 +14086,15 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/jsep": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz",
+ "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.16.0"
+ }
+ },
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
@@ -13697,6 +14155,26 @@
"integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==",
"license": "BSD-2-Clause"
},
+ "node_modules/json-stable-stringify": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
+ "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "isarray": "^2.0.5",
+ "jsonify": "^0.0.1",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
@@ -13730,8 +14208,8 @@
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
+ "devOptional": true,
"license": "MIT",
- "optional": true,
"dependencies": {
"universalify": "^2.0.0"
},
@@ -13739,6 +14217,16 @@
"graceful-fs": "^4.1.6"
}
},
+ "node_modules/jsonify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz",
+ "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==",
+ "dev": true,
+ "license": "Public Domain",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/jsonld": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/jsonld/-/jsonld-6.0.0.tgz",
@@ -13901,9 +14389,9 @@
}
},
"node_modules/jsonpath": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.2.1.tgz",
- "integrity": "sha512-Jl6Jhk0jG+kP3yk59SSeGq7LFPR4JQz1DU0K+kXTysUhMostbhU3qh5mjTuf0PqFcXpAT7kvmMt9WxV10NyIgQ==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.3.0.tgz",
+ "integrity": "sha512-0kjkYHJBkAy50Z5QzArZ7udmvxrJzkpKYW27fiF//BrMY7TQibYLl+FYIXN2BiYmwMIVzSfD8aDRj6IzgBX2/w==",
"license": "MIT",
"dependencies": {
"esprima": "1.2.5",
@@ -13911,6 +14399,24 @@
"underscore": "1.13.6"
}
},
+ "node_modules/jsonpath-plus": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz",
+ "integrity": "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jsep-plugin/assignment": "^1.3.0",
+ "@jsep-plugin/regex": "^1.0.4",
+ "jsep": "^1.4.0"
+ },
+ "bin": {
+ "jsonpath": "bin/jsonpath-cli.js",
+ "jsonpath-plus": "bin/jsonpath-cli.js"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/jsonpath/node_modules/escodegen": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
@@ -14047,6 +14553,16 @@
"json-buffer": "3.0.1"
}
},
+ "node_modules/klaw-sync": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
+ "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.1.11"
+ }
+ },
"node_modules/kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -14235,9 +14751,9 @@
}
},
"node_modules/lodash": {
- "version": "4.17.23",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
- "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"license": "MIT"
},
"node_modules/lodash.debounce": {
@@ -14452,9 +14968,9 @@
}
},
"node_modules/micromatch/node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"devOptional": true,
"license": "MIT",
"engines": {
@@ -14553,10 +15069,10 @@
}
},
"node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "license": "ISC",
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
+ "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
+ "license": "BlueOak-1.0.0",
"peer": true,
"engines": {
"node": ">=16 || 14 >=14.17"
@@ -14622,6 +15138,12 @@
"ufo": "^1.6.1"
}
},
+ "node_modules/module-alias": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.3.4.tgz",
+ "integrity": "sha512-bOclZt8hkpuGgSSoG07PKmvzTizROilUTvLNyrMqvlC9snhs7y7GzjNWAVbISIOlhCP1T14rH1PDAV9iNyBq/w==",
+ "license": "MIT"
+ },
"node_modules/mrklt": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/mrklt/-/mrklt-0.2.0.tgz",
@@ -14980,6 +15502,23 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -15111,6 +15650,61 @@
"node": ">= 0.8"
}
},
+ "node_modules/patch-package": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz",
+ "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@yarnpkg/lockfile": "^1.1.0",
+ "chalk": "^4.1.2",
+ "ci-info": "^3.7.0",
+ "cross-spawn": "^7.0.3",
+ "find-yarn-workspace-root": "^2.0.0",
+ "fs-extra": "^10.0.0",
+ "json-stable-stringify": "^1.0.2",
+ "klaw-sync": "^6.0.0",
+ "minimist": "^1.2.6",
+ "open": "^7.4.2",
+ "semver": "^7.5.3",
+ "slash": "^2.0.0",
+ "tmp": "^0.2.4",
+ "yaml": "^2.2.2"
+ },
+ "bin": {
+ "patch-package": "index.js"
+ },
+ "engines": {
+ "node": ">=14",
+ "npm": ">5"
+ }
+ },
+ "node_modules/patch-package/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/patch-package/node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -15194,9 +15788,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -15448,9 +16042,9 @@
}
},
"node_modules/protobufjs": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz",
- "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==",
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.0.1.tgz",
+ "integrity": "sha512-NWWCCscLjs+cOKF/s/XVNFRW7Yih0fdH+9brffR5NZCy8k42yRdl5KlWKMVXuI1vfCoy4o1z80XR/W/QUb3V3w==",
"hasInstallScript": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -15484,12 +16078,6 @@
"node": ">= 0.10"
}
},
- "node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
- "license": "MIT"
- },
"node_modules/pump": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
@@ -16919,9 +17507,9 @@
"license": "MIT"
},
"node_modules/strtok3": {
- "version": "10.3.4",
- "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz",
- "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==",
+ "version": "10.3.5",
+ "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.5.tgz",
+ "integrity": "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==",
"license": "MIT",
"dependencies": {
"@tokenizer/token": "^0.3.0"
@@ -17159,6 +17747,16 @@
"node": ">=14.0.0"
}
},
+ "node_modules/tmp": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
+ "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
"node_modules/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
@@ -17997,9 +18595,9 @@
"license": "MIT"
},
"node_modules/undici": {
- "version": "6.23.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
- "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz",
+ "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==",
"license": "MIT",
"engines": {
"node": ">=18.17"
@@ -18059,8 +18657,8 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "devOptional": true,
"license": "MIT",
- "optional": true,
"engines": {
"node": ">= 10.0.0"
}
@@ -18205,9 +18803,9 @@
"optional": true
},
"node_modules/vite": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
- "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
+ "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -19248,6 +19846,22 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"license": "ISC"
},
+ "node_modules/yaml": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
+ "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
"node_modules/yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
diff --git a/package.json b/package.json
index c324505..f7da486 100644
--- a/package.json
+++ b/package.json
@@ -5,17 +5,24 @@
"private": true,
"type": "module",
"scripts": {
- "build": "npm run build --workspace=packages/mcp-shared && npm run build --workspace=apps/truvera-api",
+ "postinstall": "node scripts/apply-wallet-patches.js",
+ "build": "npm run build --workspace=packages/mcp-shared && npm run build --workspace=apps/truvera-api && npm run build --workspace=apps/wallet-server",
"build:shared": "npm run build --workspace=packages/mcp-shared",
"build:api": "npm run build --workspace=apps/truvera-api",
+ "build:wallet": "npm run build --workspace=apps/wallet-server",
"dev:api": "npm run dev --workspace=apps/truvera-api",
+ "dev:wallet": "npm run dev --workspace=apps/wallet-server",
"test": "npm run test --workspaces",
"test:api": "npm run test --workspace=apps/truvera-api",
+ "test:wallet": "npm run test --workspace=apps/wallet-server",
+ "test:wallet:integration": "npm run test:integration --workspace=apps/wallet-server",
"typecheck": "npm run typecheck --workspaces",
"lint": "npm run lint --workspaces",
"lint:fix": "npm run lint:fix --workspaces",
"docker:build:api": "docker build --build-arg BUILD_NUMBER=\"$(cat apps/truvera-api/.buildnumber)\" -t docknetwork/truvera-api-mcp:latest -t docknetwork/truvera-api-mcp:$(cat apps/truvera-api/.buildnumber) -f apps/truvera-api/Dockerfile .",
- "docker:run:api": "docker rm -f truvera-api-mcp || true && docker run -d --name truvera-api-mcp --env-file apps/truvera-api/.env -e MCP_MODE=http -e MCP_PORT=3000 -p 3000:3000 docknetwork/truvera-api-mcp:latest"
+ "docker:run:api": "docker rm -f truvera-api-mcp || true && docker run -d --name truvera-api-mcp --env-file apps/truvera-api/.env -e MCP_MODE=http -e MCP_PORT=3000 -p 3000:3000 docknetwork/truvera-api-mcp:latest",
+ "docker:build:wallet": "docker build --build-arg BUILD_NUMBER=\"$(cat apps/wallet-server/.buildnumber)\" -t docknetwork/truvera-wallet-mcp:latest -t docknetwork/truvera-wallet-mcp:$(cat apps/wallet-server/.buildnumber) -f apps/wallet-server/Dockerfile .",
+ "docker:run:wallet": "docker rm -f truvera-wallet-mcp || true && docker run -d --name truvera-wallet-mcp --env-file apps/wallet-server/.env -e MCP_MODE=http -e MCP_PORT=3001 -p 3001:3001 docknetwork/truvera-wallet-mcp:latest"
},
"workspaces": [
"packages/*",
@@ -53,5 +60,8 @@
"repository": {
"type": "git",
"url": "https://github.com/docknetwork/truvera-mcp-server.git"
+ },
+ "devDependencies": {
+ "patch-package": "^8.0.1"
}
}
diff --git a/packages/mcp-shared/src/server/bootstrap.ts b/packages/mcp-shared/src/server/bootstrap.ts
index a6fcaa8..c2c1235 100644
--- a/packages/mcp-shared/src/server/bootstrap.ts
+++ b/packages/mcp-shared/src/server/bootstrap.ts
@@ -69,11 +69,12 @@ export async function bootstrapMCPServer(
// Start the appropriate transport
if (transportConfig.mode === "http") {
const port = transportConfig.port ?? 3000;
- startHTTPTransport({
+ await startHTTPTransport({
serverFactory: createServer,
MCP_PORT: port,
BUILD_INFO: buildInfo,
tools,
+ serviceName: name,
});
} else {
const server = createServer();
diff --git a/packages/mcp-shared/src/transport/http/index.test.ts b/packages/mcp-shared/src/transport/http/index.test.ts
new file mode 100644
index 0000000..741b632
--- /dev/null
+++ b/packages/mcp-shared/src/transport/http/index.test.ts
@@ -0,0 +1,86 @@
+import http from "node:http";
+import type { AddressInfo } from "node:net";
+import { afterEach, describe, expect, it, vi } from "vitest";
+import { findNextAvailablePort, resolvePortConflict } from "./index.js";
+
+describe("findNextAvailablePort", () => {
+ let occupiedServer: http.Server | undefined;
+
+ afterEach(async () => {
+ if (!occupiedServer) {
+ return;
+ }
+
+ await new Promise((resolve, reject) => {
+ occupiedServer!.close((error?: Error) => {
+ if (error) {
+ reject(error);
+ return;
+ }
+
+ resolve();
+ });
+ });
+
+ occupiedServer = undefined;
+ });
+
+ it("returns a higher port when the starting port is occupied", async () => {
+ occupiedServer = http.createServer();
+
+ await new Promise((resolve) => {
+ occupiedServer!.listen(0, "127.0.0.1", () => resolve());
+ });
+
+ const occupiedPort = (occupiedServer.address() as AddressInfo).port;
+ const availablePort = await findNextAvailablePort(occupiedPort);
+
+ expect(availablePort).toBeGreaterThan(occupiedPort);
+ });
+});
+
+describe("resolvePortConflict", () => {
+ it("returns the next port when the user accepts the prompt", async () => {
+ const promptUser = vi.fn().mockResolvedValue("");
+ const findPort = vi.fn().mockResolvedValue(3001);
+
+ await expect(
+ resolvePortConflict(3000, "wallet-mcp-service", {
+ isInteractive: true,
+ findNextAvailablePort: findPort,
+ promptUser,
+ })
+ ).resolves.toBe(3001);
+
+ expect(findPort).toHaveBeenCalledWith(3001);
+ expect(promptUser).toHaveBeenCalledWith(
+ "Port 3000 is already in use. Start wallet-mcp-service on port 3001 instead? [Y/n] "
+ );
+ });
+
+ it("throws when no interactive terminal is available", async () => {
+ const promptUser = vi.fn();
+
+ await expect(
+ resolvePortConflict(3000, "wallet-mcp-service", {
+ isInteractive: false,
+ findNextAvailablePort: vi.fn().mockResolvedValue(3001),
+ promptUser,
+ })
+ ).rejects.toThrow(
+ "Port 3000 is already in use. wallet-mcp-service can run on 3001, but no interactive terminal is available to confirm it."
+ );
+
+ expect(promptUser).not.toHaveBeenCalled();
+ });
+
+ it("throws when the user declines the alternate port", async () => {
+ await expect(
+ resolvePortConflict(3000, "wallet-mcp-service", {
+ isInteractive: true,
+ findNextAvailablePort: vi.fn().mockResolvedValue(3001),
+ promptUser: vi.fn().mockResolvedValue("n"),
+ })
+ ).rejects.toThrow("Startup cancelled because port 3000 is already in use.");
+ });
+});
\ No newline at end of file
diff --git a/packages/mcp-shared/src/transport/http/index.ts b/packages/mcp-shared/src/transport/http/index.ts
index f11da81..60e0245 100644
--- a/packages/mcp-shared/src/transport/http/index.ts
+++ b/packages/mcp-shared/src/transport/http/index.ts
@@ -1,6 +1,8 @@
-import http from "http";
+import http, { type IncomingMessage, type ServerResponse } from "node:http";
+import net from "node:net";
+import readline from "node:readline/promises";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
-import { randomUUID } from "crypto";
+import { randomUUID } from "node:crypto";
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import type { ToolDef } from "../../tools/types.js";
@@ -14,7 +16,132 @@ export interface HTTPTransportArgs {
serviceName?: string;
}
-export function startHTTPTransport({
+interface ResolvePortConflictOptions {
+ isInteractive?: boolean;
+ findNextAvailablePort?: (startPort: number) => Promise;
+ promptUser?: (message: string) => Promise;
+}
+
+function isPortInUseError(error: unknown): error is NodeJS.ErrnoException {
+ return error instanceof Error && "code" in error && (error as NodeJS.ErrnoException).code === "EADDRINUSE";
+}
+
+async function isPortAvailable(port: number): Promise {
+ return new Promise((resolve, reject) => {
+ const probeServer = net.createServer();
+
+ probeServer.once("error", (error: Error) => {
+ if (isPortInUseError(error)) {
+ resolve(false);
+ return;
+ }
+
+ reject(error);
+ });
+
+ probeServer.once("listening", () => {
+ probeServer.close((closeError?: Error) => {
+ if (closeError) {
+ reject(closeError);
+ return;
+ }
+
+ resolve(true);
+ });
+ });
+
+ probeServer.listen(port, "0.0.0.0");
+ });
+}
+
+export async function findNextAvailablePort(startPort: number): Promise {
+ for (let candidatePort = startPort; candidatePort <= 65535; candidatePort += 1) {
+ if (await isPortAvailable(candidatePort)) {
+ return candidatePort;
+ }
+ }
+
+ throw new Error(`No available port found starting at ${startPort}.`);
+}
+
+async function promptUserForAlternatePort(message: string): Promise {
+ const rl = readline.createInterface({
+ input: process.stdin,
+ output: process.stderr,
+ });
+
+ try {
+ return await rl.question(message);
+ } finally {
+ rl.close();
+ }
+}
+
+export async function resolvePortConflict(
+ requestedPort: number,
+ serviceName: string,
+ options: ResolvePortConflictOptions = {}
+): Promise {
+ const isInteractive = options.isInteractive ?? Boolean(process.stdin.isTTY && process.stderr.isTTY);
+ const nextAvailablePort = await (options.findNextAvailablePort ?? findNextAvailablePort)(requestedPort + 1);
+
+ if (!isInteractive) {
+ throw new Error(
+ `Port ${requestedPort} is already in use. ${serviceName} can run on ${nextAvailablePort}, but no interactive terminal is available to confirm it.`
+ );
+ }
+
+ const answer = await (options.promptUser ?? promptUserForAlternatePort)(
+ `Port ${requestedPort} is already in use. Start ${serviceName} on port ${nextAvailablePort} instead? [Y/n] `
+ );
+ const normalizedAnswer = answer.trim().toLowerCase();
+
+ if (normalizedAnswer === "" || normalizedAnswer === "y" || normalizedAnswer === "yes") {
+ return nextAvailablePort;
+ }
+
+ throw new Error(`Startup cancelled because port ${requestedPort} is already in use.`);
+}
+
+async function listenOnPort(httpServer: http.Server, requestedPort: number, serviceName: string): Promise {
+ let port = requestedPort;
+
+ while (true) {
+ try {
+ await new Promise((resolve, reject) => {
+ const onError = (error: Error) => {
+ cleanup();
+ reject(error);
+ };
+
+ const onListening = () => {
+ cleanup();
+ resolve();
+ };
+
+ const cleanup = () => {
+ httpServer.off("error", onError);
+ httpServer.off("listening", onListening);
+ };
+
+ httpServer.once("error", onError);
+ httpServer.once("listening", onListening);
+ httpServer.listen(port, "0.0.0.0");
+ });
+
+ return port;
+ } catch (error) {
+ if (!isPortInUseError(error)) {
+ throw error;
+ }
+
+ port = await resolvePortConflict(port, serviceName);
+ console.error(`[HTTP] Retrying ${serviceName} on port ${port}`);
+ }
+ }
+}
+
+export async function startHTTPTransport({
serverFactory,
MCP_PORT,
BUILD_INFO,
@@ -27,7 +154,7 @@ export function startHTTPTransport({
return !!body && typeof body === "object" && "method" in body && (body as Record).method === "initialize";
}
- const httpServer = http.createServer(async (req, res) => {
+ const httpServer = http.createServer(async (req: IncomingMessage, res: ServerResponse) => {
// Debug: Log all incoming requests
console.error("[DEBUG] Incoming request:", {
method: req.method,
@@ -68,7 +195,7 @@ export function startHTTPTransport({
if (req.method === "POST") {
body = await new Promise((resolve, reject) => {
let data = "";
- req.on("data", (chunk) => {
+ req.on("data", (chunk: Buffer) => {
data += chunk;
});
req.on("end", () => {
@@ -185,12 +312,12 @@ export function startHTTPTransport({
res.end(JSON.stringify({ error: "Not found. Use POST /mcp for MCP communication." }));
});
- httpServer.listen(MCP_PORT, "0.0.0.0", () => {
- console.error(`${serviceName} started (HTTP streaming mode on port ${MCP_PORT})`);
- console.error(` - Build: ${BUILD_INFO.buildNumber} (${BUILD_INFO.timestamp})`);
- console.error(` - MCP endpoint: POST http://localhost:${MCP_PORT}/mcp`);
- console.error(` - Health check: GET http://localhost:${MCP_PORT}/health`);
- });
+ const activePort = await listenOnPort(httpServer, MCP_PORT, serviceName);
+
+ console.error(`${serviceName} started (HTTP streaming mode on port ${activePort})`);
+ console.error(` - Build: ${BUILD_INFO.buildNumber} (${BUILD_INFO.timestamp})`);
+ console.error(` - MCP endpoint: POST http://localhost:${activePort}/mcp`);
+ console.error(` - Health check: GET http://localhost:${activePort}/health`);
// Handle graceful shutdown
process.on("SIGINT", () => {
diff --git a/packages/mcp-shared/tsconfig.json b/packages/mcp-shared/tsconfig.json
index 917348e..2c09953 100644
--- a/packages/mcp-shared/tsconfig.json
+++ b/packages/mcp-shared/tsconfig.json
@@ -11,6 +11,7 @@
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
+ "types": ["node"],
"declaration": true,
"declarationMap": true,
"sourceMap": true
diff --git a/scripts/apply-wallet-patches.js b/scripts/apply-wallet-patches.js
new file mode 100644
index 0000000..c0b74af
--- /dev/null
+++ b/scripts/apply-wallet-patches.js
@@ -0,0 +1,59 @@
+#!/usr/bin/env node
+
+import fs from 'fs';
+import path from 'path';
+import { spawnSync } from 'child_process';
+import { fileURLToPath } from 'url';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const repoRoot = path.resolve(__dirname, '..');
+const patchDir = path.join(repoRoot, 'apps/wallet-server/patches');
+const nodeModulesDir = path.join(repoRoot, 'node_modules');
+const patchPackageBinary = process.platform === 'win32' ? 'patch-package.cmd' : 'patch-package';
+
+function getPackageNameFromPatchFile(fileName) {
+ const baseName = fileName.replace(/\.patch$/, '');
+ const parts = baseName.split('+');
+
+ if (baseName.startsWith('@') && parts.length >= 3) {
+ return `${parts[0]}/${parts[1]}`;
+ }
+
+ return parts.slice(0, -1).join('+');
+}
+
+function isPatchPackageAvailable() {
+ const result = spawnSync(patchPackageBinary, ['--version'], {
+ cwd: repoRoot,
+ stdio: 'ignore',
+ });
+
+ return result.status === 0;
+}
+
+if (!fs.existsSync(patchDir)) {
+ process.exit(0);
+}
+
+if (!isPatchPackageAvailable()) {
+ console.log('Skipping wallet patches because patch-package is not available in this install context.');
+ process.exit(0);
+}
+
+const patchFiles = fs.readdirSync(patchDir).filter((file) => file.endsWith('.patch'));
+const installedPatchTargets = patchFiles.filter((file) => {
+ const packageName = getPackageNameFromPatchFile(file);
+ return packageName && fs.existsSync(path.join(nodeModulesDir, packageName));
+});
+
+if (installedPatchTargets.length === 0) {
+ console.log('Skipping wallet patches because patched wallet dependencies are not installed.');
+ process.exit(0);
+}
+
+const result = spawnSync(patchPackageBinary, ['--patch-dir', path.relative(repoRoot, patchDir)], {
+ cwd: repoRoot,
+ stdio: 'inherit',
+});
+
+process.exit(result.status ?? 1);
\ No newline at end of file