diff --git a/.github/actions/setup_canton/action.yml b/.github/actions/setup_canton/action.yml new file mode 100644 index 000000000..1e7845e60 --- /dev/null +++ b/.github/actions/setup_canton/action.yml @@ -0,0 +1,95 @@ +name: 'Setup Canton/Localnet' +description: 'Cache, download and prepare Canton or Localnet environment' +inputs: + network: + description: 'Network type: canton, devnet, or mainnet' + required: false + default: 'devnet' +runs: + using: 'composite' + steps: + - name: Cache Canton binaries + if: inputs.network == 'canton' + uses: actions/cache@v4 + id: canton-cache + with: + path: .canton + key: ${{ runner.os }}-canton-${{ hashFiles('scripts/src/lib/version-config.json') }} + + - name: Create Docker cache directory + if: inputs.network != 'canton' + shell: bash + run: mkdir -p /tmp/docker-images + + - name: Cache Localnet + if: inputs.network != 'canton' + uses: actions/cache@v4 + id: localnet-cache + with: + path: .localnet + key: ${{ runner.os }}-localnet-${{ inputs.network }}-${{ hashFiles('scripts/src/lib/version-config.json') }} + + - name: Cache Docker images + if: inputs.network != 'canton' + uses: actions/cache@v4 + id: docker-cache + with: + path: /tmp/docker-images + key: ${{ runner.os }}-docker-localnet-${{ inputs.network }}-${{ hashFiles('scripts/src/lib/version-config.json') }} + restore-keys: | + ${{ runner.os }}-docker-localnet-${{ inputs.network }}- + + - name: Load cached Docker images + if: inputs.network != 'canton' && steps.docker-cache.outputs.cache-hit == 'true' + shell: bash + run: | + if [ -f /tmp/docker-images/images.tar ]; then + docker load -i /tmp/docker-images/images.tar + fi + + - name: Download Canton + if: inputs.network == 'canton' && steps.canton-cache.outputs.cache-hit != 'true' + shell: bash + run: yarn script:fetch:canton + + - name: Download Localnet + if: inputs.network != 'canton' && (steps.localnet-cache.outputs.cache-hit != 'true' || steps.docker-cache.outputs.cache-hit != 'true') + shell: bash + run: yarn script:fetch:localnet -- --network=${{ inputs.network }} + + - name: Start Canton + if: inputs.network == 'canton' + shell: bash + run: | + set -e + timeout 5m bash -c ' + LOGFILE=canton_start.log + yarn start:canton > "$LOGFILE" 2>&1 & + pid=$! + for i in {1..60}; do + if grep -q "Bootstrap script successfully executed." "$LOGFILE"; then + echo "Canton started successfully." + exit 0 + fi + if ! kill -0 $pid 2>/dev/null; then + echo "Canton process exited unexpectedly." + cat "$LOGFILE" + exit 1 + fi + sleep 5 + done + echo "Timeout: '"'"'Bootstrap script successfully executed.'"'"' not found in 5 minutes." + cat "$LOGFILE" + exit 1 + ' + + - name: Start Localnet + if: inputs.network != 'canton' + shell: bash + run: yarn start:localnet -- --network=${{ inputs.network }} + + - name: Save Docker images to cache + if: inputs.network != 'canton' && steps.docker-cache.outputs.cache-hit != 'true' + shell: bash + run: | + docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "" | xargs -r docker save -o /tmp/docker-images/images.tar diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a4d178042..6f9432cfe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,6 +7,10 @@ on: permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest @@ -111,41 +115,16 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - uses: ./.github/actions/setup_yarn - - name: Download Canton - run: yarn script:fetch:canton + - uses: ./.github/actions/setup_yarn - - name: Build project - run: yarn build:all + - uses: ./.github/actions/setup_canton + with: + network: canton - name: Start remote WK run: yarn nx run @canton-network/wallet-gateway-remote:start & - - name: Start Canton - run: | - set -e - timeout 5m bash -c ' - LOGFILE=canton_start.log - yarn start:canton > "$LOGFILE" 2>&1 & - pid=$! - for i in {1..60}; do - if grep -q "Bootstrap script successfully executed." "$LOGFILE"; then - echo "Canton started successfully." - exit 0 - fi - if ! kill -0 $pid 2>/dev/null; then - echo "Canton process exited unexpectedly." - cat "$LOGFILE" - exit 1 - fi - sleep 5 - done - echo "Timeout: 'Bootstrap script successfully executed.' not found in 5 minutes." - cat "$LOGFILE" - exit 1 - ' - - run: yarn nx run @canton-network/example-ping:dev > "example-ping.log" 2>&1 & - run: yarn nx run @canton-network/mock-oauth2:start & @@ -177,20 +156,12 @@ jobs: uses: actions/checkout@v4 - uses: ./.github/actions/setup_yarn - - name: Download Canton - run: yarn script:fetch:localnet - - - name: Start LocalNet - run: yarn start:localnet + - uses: ./.github/actions/setup_canton + # for some reason it breaks if we don't have a build here... - name: Build project run: yarn build:all - - name: Increase rate limit in wallet gateway config - run: | - jq '.server.requestRateLimit = 10000' wallet-gateway/test/config.json >/tmp/e2e-wk-config.json - mv /tmp/e2e-wk-config.json wallet-gateway/test/config.json - - name: Start remote WK run: yarn nx run @canton-network/wallet-gateway-remote:start > "wallet-gateway-remote.log" 2>&1 & @@ -232,11 +203,9 @@ jobs: - uses: ./.github/actions/setup_yarn - - name: Download localnet (${{ matrix.network }}) - run: yarn script:fetch:localnet -- --network=${{ matrix.network }} - - - name: Start Localnet (${{ matrix.network }}) - run: yarn start:localnet -- --network=${{ matrix.network }} + - uses: ./.github/actions/setup_canton + with: + network: ${{ matrix.network }} - uses: ./.github/actions/check_resources diff --git a/.github/workflows/examples-under-stress.yml b/.github/workflows/examples-under-stress.yml index da8dcf93e..41685e50e 100644 --- a/.github/workflows/examples-under-stress.yml +++ b/.github/workflows/examples-under-stress.yml @@ -48,11 +48,9 @@ jobs: - name: Build project run: yarn build:all - - name: Download localnet (${{ github.event.inputs.network || 'devnet' }}) - run: yarn script:fetch:localnet -- --network=${{ github.event.inputs.network || 'devnet' }} - - - name: Start localnet (${{ github.event.inputs.network || 'devnet' }}) - run: yarn start:localnet -- --network=${{ github.event.inputs.network || 'devnet' }} + - uses: ./.github/actions/setup_canton + with: + network: ${{ github.event.inputs.network || 'devnet' }} - uses: ./.github/actions/check_resources diff --git a/.github/workflows/stress-tests.yml b/.github/workflows/stress-tests.yml index ed444c3c8..48d67a132 100644 --- a/.github/workflows/stress-tests.yml +++ b/.github/workflows/stress-tests.yml @@ -32,11 +32,9 @@ jobs: - name: Build project run: yarn build:all - - name: Download localnet (${{ github.event.inputs.network || 'devnet' }}) - run: yarn script:fetch:localnet -- --network=${{ github.event.inputs.network || 'devnet' }} - - - name: Start localnet (${{ github.event.inputs.network || 'devnet' }}) - run: yarn start:localnet -- --network=${{ github.event.inputs.network || 'devnet' }} + - uses: ./.github/actions/setup_canton + with: + network: ${{ github.event.inputs.network || 'devnet' }} - uses: ./.github/actions/check_resources diff --git a/api-specs/openrpc-dapp-api.json b/api-specs/openrpc-dapp-api.json index 8a59bb8b8..ede056fd5 100644 --- a/api-specs/openrpc-dapp-api.json +++ b/api-specs/openrpc-dapp-api.json @@ -3,7 +3,7 @@ "info": { "title": "Splice Wallet JSON-RPC dApp API", "version": "0.5.0", - "description": "An OpenRPC specification for the dapp to interact with a Wallet Gateway." + "description": "An OpenRPC specification for the dapp to interact with a Wallet Provider." }, "methods": [ { @@ -15,7 +15,7 @@ "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/StatusEvent" } }, - "description": "Returns the current status of the wallet gateway session." + "description": "Returns the current status of the wallet provider session." }, { "name": "connect", @@ -23,10 +23,10 @@ "result": { "name": "result", "schema": { - "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/StatusEvent" + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/ConnectResult" } }, - "description": "Ensures ledger connectivity and returns the connected network information along with the user access token. Network ID should follow CAIP-2 and represent the synchronizerId." + "description": "Ensures ledger connectivity and returns the connected network information along with the session information." }, { "name": "disconnect", @@ -37,7 +37,7 @@ "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/Null" } }, - "description": "Invoke a disconnect of the wallet gateway session." + "description": "Invoke a disconnect of the wallet provider session." }, { "name": "getActiveNetwork", @@ -183,26 +183,31 @@ "type": "null", "description": "Represents a null value, used in responses where no data is returned." }, - "KernelInfo": { - "title": "KernelInfo", + "Provider": { + "title": "Provider", "type": "object", - "description": "Represents a Wallet Gateway.", + "description": "Represents a Provider.", "properties": { "id": { "title": "id", "type": "string", - "description": "The unique identifier of the Wallet Gateway." + "description": "The unique identifier of the Provider." + }, + "version": { + "title": "version", + "type": "string", + "description": "The version of the Provider." }, - "clientType": { - "title": "clientType", + "providerType": { + "title": "providerType", "type": "string", "enum": ["browser", "desktop", "mobile", "remote"], - "description": "The type of client that implements the Wallet Gateway." + "description": "The type of client that implements the Provider." }, "url": { "title": "url", "type": "string", - "description": "The URL of the Wallet Gateway." + "description": "The URL of the Wallet Provider." }, "userUrl": { "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/UserUrl" @@ -512,18 +517,20 @@ } ] }, - "StatusEvent": { - "title": "StatusEvent", + "ConnectResult": { + "title": "ConnectResult", "type": "object", "properties": { - "kernel": { - "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/KernelInfo" - }, "isConnected": { "title": "isConnected", "type": "boolean", "description": "Whether or not the user is authenticated with the Wallet." }, + "reason": { + "title": "reason", + "type": "string", + "description": "The reason why the user is not connected to the Wallet." + }, "isNetworkConnected": { "title": "isNetworkConnected", "type": "boolean", @@ -533,30 +540,28 @@ "title": "networkReason", "type": "string", "description": "If not connected to a network, the reason why." + } + }, + "required": ["isConnected", "isNetworkConnected"] + }, + "StatusEvent": { + "title": "StatusEvent", + "type": "object", + "properties": { + "provider": { + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/Provider" + }, + "connection": { + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/ConnectResult" }, "network": { "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/Network" }, "session": { - "title": "session", - "type": "object", - "description": "Session information, if authenticated.", - "properties": { - "accessToken": { - "title": "accessToken", - "type": "string", - "description": "JWT authentication token." - }, - "userId": { - "title": "userId", - "type": "string", - "description": "The user identifier." - } - }, - "required": ["accessToken", "userId"] + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/Session" } }, - "required": ["kernel", "isConnected", "isNetworkConnected"] + "required": ["provider", "connection"] }, "SignMessageRequest": { "title": "SignMessageRequest", @@ -595,21 +600,37 @@ "description": "A CAIP-2 compliant chain ID, e.g. 'canton:da-mainnet'." }, "ledgerApi": { - "title": "LedgerApiConfig", - "type": "object", - "description": "Ledger API configuration.", - "properties": { - "baseUrl": { - "title": "baseUrl", - "type": "string", - "format": "uri", - "description": "The base URL of the ledger API." - } - }, - "required": ["baseUrl"] + "title": "ledgerApiUrl", + "type": "string", + "description": "The base URL of the ledger API.", + "format": "uri" + }, + "accessToken": { + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/AccessToken" } }, "required": ["networkId"] + }, + "AccessToken": { + "title": "accessToken", + "type": "string", + "description": "JWT authentication token." + }, + "Session": { + "title": "session", + "type": "object", + "description": "Session information, if authenticated.", + "properties": { + "accessToken": { + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/AccessToken" + }, + "userId": { + "title": "userId", + "type": "string", + "description": "The user identifier." + } + }, + "required": ["accessToken", "userId"] } } } diff --git a/api-specs/openrpc-dapp-remote-api.json b/api-specs/openrpc-dapp-remote-api.json index 1b88d8929..df9013fca 100644 --- a/api-specs/openrpc-dapp-remote-api.json +++ b/api-specs/openrpc-dapp-remote-api.json @@ -3,7 +3,7 @@ "info": { "title": "Splice Wallet JSON-RPC Remote dApp API", "version": "0.1.0", - "description": "An OpenRPC specification for remotely hosted Wallet Gateways. Due to the remote nature, an implementing provider must bridge certain functionality on the client-side to satisfy the general dApp API spec." + "description": "An OpenRPC specification for remotely hosted Wallet Providers. Due to the remote nature, an implementing provider must bridge certain functionality on the client-side to satisfy the general dApp API spec." }, "methods": [ { @@ -15,7 +15,7 @@ "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/StatusEvent" } }, - "description": "Returns the current status of the wallet gateway session." + "description": "Returns the current status of the wallet provider session." }, { "name": "connect", @@ -23,25 +23,10 @@ "result": { "name": "result", "schema": { - "title": "StatusEventAsync", - "allOf": [ - { - "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/StatusEvent" - }, - { - "type": "object", - "title": "ConnectResult", - "properties": { - "userUrl": { - "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/UserUrl" - } - }, - "required": ["userUrl"] - } - ] + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/ConnectResult" } }, - "description": "Ensures ledger connectivity and returns the connected network information along with the user access token. NetworkId should follow CAIP-2 and represent the synchronizerId." + "description": "Ensures ledger connectivity and returns the connected network information." }, { "name": "disconnect", diff --git a/core/asyncapi-client/README.md b/core/asyncapi-client/README.md new file mode 100644 index 000000000..2d8f9b111 --- /dev/null +++ b/core/asyncapi-client/README.md @@ -0,0 +1 @@ +# asyncapi-client diff --git a/core/asyncapi-client/jest.config.ts b/core/asyncapi-client/jest.config.ts new file mode 100644 index 000000000..d3f35fd6f --- /dev/null +++ b/core/asyncapi-client/jest.config.ts @@ -0,0 +1,13 @@ +// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import type { Config } from 'jest' + +export default { + rootDir: 'src', + extensionsToTreatAsEsm: ['.ts'], + resolver: 'ts-jest-resolver', + transform: { + '^.+\\.(t|j)sx?$': '@swc/jest', + }, +} satisfies Config diff --git a/core/asyncapi-client/package.json b/core/asyncapi-client/package.json new file mode 100644 index 000000000..54d432dcc --- /dev/null +++ b/core/asyncapi-client/package.json @@ -0,0 +1,58 @@ +{ + "name": "@canton-network/core-asyncapi-client", + "version": "0.1.0", + "type": "module", + "description": "Provides a TypeScript asyncapi ledger client, generated by the OpenAPI spec", + "license": "Apache-2.0", + "author": "Phillip Olesen ", + "packageManager": "yarn@4.9.4", + "main": "dist/index.cjs", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs", + "default": "./dist/index.js" + } + }, + "scripts": { + "build": "tsup && tsc -p tsconfig.types.json", + "dev": "tsup --watch --onSuccess \"tsc -p tsconfig.types.json\"", + "clean": "tsc -b --clean; rm -rf dist", + "flatpack": "yarn pack --out \"$FLATPACK_OUTDIR\"", + "test": "jest --passWithNoTests" + }, + "devDependencies": { + "@jest/globals": "^30.2.0", + "@swc/core": "^1.15.10", + "@swc/jest": "^0.2.39", + "@types/jest": "^30.0.0", + "@types/node": "^25.0.10", + "jest": "^30.2.0", + "openapi-typescript": "^7.10.1", + "ts-jest": "^29.4.6", + "ts-jest-resolver": "^2.0.1", + "tsup": "^8.5.1", + "typescript": "^5.9.3" + }, + "dependencies": { + "@canton-network/core-ledger-client-types": "workspace:^", + "@canton-network/core-types": "workspace:^", + "@canton-network/core-wallet-auth": "workspace:^", + "bignumber.js": "^9.3.1", + "pino": "^10.2.1" + }, + "files": [ + "dist/**" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hyperledger-labs/splice-wallet-kernel.git", + "directory": "core/asyncapi-client" + } +} diff --git a/core/asyncapi-client/src/index.ts b/core/asyncapi-client/src/index.ts new file mode 100644 index 000000000..c710940ab --- /dev/null +++ b/core/asyncapi-client/src/index.ts @@ -0,0 +1,4 @@ +// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +export * from './websocket-client.js' diff --git a/core/ledger-client/src/web-socket-client.ts b/core/asyncapi-client/src/websocket-client.ts similarity index 94% rename from core/ledger-client/src/web-socket-client.ts rename to core/asyncapi-client/src/websocket-client.ts index dc97e9123..05126b8a4 100644 --- a/core/ledger-client/src/web-socket-client.ts +++ b/core/asyncapi-client/src/websocket-client.ts @@ -5,9 +5,9 @@ import { PartyId } from '@canton-network/core-types' import { CHANNELS, JsGetUpdatesResponse, -} from './generated-clients/asyncapi-3.4.7.js' + TransactionFilterBySetup, +} from '@canton-network/core-ledger-client-types' import { Logger } from 'pino' -import { TransactionFilterBySetup } from './ledger-api-utils.js' import { AccessTokenProvider } from '@canton-network/core-wallet-auth' type UpdateSubscriptionOptions = { @@ -27,13 +27,11 @@ type CommandsCompletionsOptions = { } export class WebSocketClient { - private ws: WebSocket | null = null private baseUrl: string private token: string = '' private isAdmin: boolean private protocol: string[] = [] private readonly logger: Logger - private wsSupportBackOff: number private accessTokenProvider: AccessTokenProvider constructor({ @@ -41,17 +39,14 @@ export class WebSocketClient { isAdmin, accessTokenProvider, logger, - wsSupportBackOff, }: { baseUrl: string isAdmin?: boolean accessTokenProvider: AccessTokenProvider logger: Logger - wsSupportBackOff: number }) { this.logger = logger.child({ component: 'WebSocketClient' }) this.baseUrl = baseUrl - this.wsSupportBackOff = wsSupportBackOff this.accessTokenProvider = accessTokenProvider this.isAdmin = isAdmin ?? false } diff --git a/core/asyncapi-client/tsconfig.json b/core/asyncapi-client/tsconfig.json new file mode 100644 index 000000000..572eba58e --- /dev/null +++ b/core/asyncapi-client/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.web.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist" + }, + "include": ["src"] +} diff --git a/core/asyncapi-client/tsconfig.types.json b/core/asyncapi-client/tsconfig.types.json new file mode 100644 index 000000000..e522515b7 --- /dev/null +++ b/core/asyncapi-client/tsconfig.types.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.web.json", + "compilerOptions": { + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true, + "rootDir": "./src", + "outDir": "./dist", + "moduleResolution": "bundler", + "noEmit": false, + "composite": false + }, + "include": ["src/**/*.ts", "src/**/*.d.ts"], + "exclude": ["**/*.test.*", "**/*.spec.*", "**/__tests__/**"] +} diff --git a/core/asyncapi-client/tsup.config.ts b/core/asyncapi-client/tsup.config.ts new file mode 100644 index 000000000..1f4074292 --- /dev/null +++ b/core/asyncapi-client/tsup.config.ts @@ -0,0 +1,10 @@ +// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { defineConfig } from 'tsup' +import { base } from '../../tsup.base' + +export default defineConfig({ + ...base, + entry: ['src/index.ts'], +}) diff --git a/core/ledger-client-types/README.md b/core/ledger-client-types/README.md new file mode 100644 index 000000000..bab9414c5 --- /dev/null +++ b/core/ledger-client-types/README.md @@ -0,0 +1 @@ +# ledger-client-types diff --git a/core/ledger-client-types/package.json b/core/ledger-client-types/package.json new file mode 100644 index 000000000..c5e5591a0 --- /dev/null +++ b/core/ledger-client-types/package.json @@ -0,0 +1,57 @@ +{ + "name": "@canton-network/core-ledger-client-types", + "version": "0.20.0", + "type": "module", + "description": "Contains TypeScript types for the Canton Network ledger client, generated by the OpenAPI spec, and utility functions", + "license": "Apache-2.0", + "author": "Phillip Olesen ", + "packageManager": "yarn@4.9.4", + "main": "dist/index.cjs", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs", + "default": "./dist/index.js" + } + }, + "scripts": { + "build": "tsup && tsc -p tsconfig.types.json", + "dev": "tsup --watch --onSuccess \"tsc -p tsconfig.types.json\"", + "flatpack": "yarn pack --out \"$FLATPACK_OUTDIR\"", + "clean": "tsc -b --clean; rm -rf dist" + }, + "devDependencies": { + "@jest/globals": "^30.2.0", + "@swc/core": "^1.15.10", + "@swc/jest": "^0.2.39", + "@types/jest": "^30.0.0", + "@types/node": "^25.0.10", + "jest": "^30.2.0", + "openapi-typescript": "^7.10.1", + "ts-jest": "^29.4.6", + "ts-jest-resolver": "^2.0.1", + "tsup": "^8.5.1", + "typescript": "^5.9.3" + }, + "dependencies": { + "@canton-network/core-types": "workspace:^", + "bignumber.js": "^9.3.1", + "dayjs": "^1.11.19", + "openapi-fetch": "^0.15.0", + "pino": "^10.2.1" + }, + "files": [ + "dist/**" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hyperledger-labs/splice-wallet-kernel.git", + "directory": "core/ledger-client-types" + } +} diff --git a/core/ledger-client/src/generated-clients/asyncapi-3.4.7.ts b/core/ledger-client-types/src/generated-clients/asyncapi-3.4.11.ts similarity index 99% rename from core/ledger-client/src/generated-clients/asyncapi-3.4.7.ts rename to core/ledger-client-types/src/generated-clients/asyncapi-3.4.11.ts index fa8b9e1ad..7fc4cdd51 100644 --- a/core/ledger-client/src/generated-clients/asyncapi-3.4.7.ts +++ b/core/ledger-client-types/src/generated-clients/asyncapi-3.4.11.ts @@ -1128,5 +1128,5 @@ export const CHANNELS = { // API Info export const API_INFO = { title: 'JSON Ledger API WebSocket endpoints', - version: '3.4.7', + version: '3.4.11-SNAPSHOT', } as const diff --git a/core/ledger-client/src/generated-clients/openapi-3.3.0-SNAPSHOT.ts b/core/ledger-client-types/src/generated-clients/openapi-3.3.0-SNAPSHOT.ts similarity index 100% rename from core/ledger-client/src/generated-clients/openapi-3.3.0-SNAPSHOT.ts rename to core/ledger-client-types/src/generated-clients/openapi-3.3.0-SNAPSHOT.ts diff --git a/core/ledger-client/src/generated-clients/openapi-3.4.7.ts b/core/ledger-client-types/src/generated-clients/openapi-3.4.11.ts similarity index 98% rename from core/ledger-client/src/generated-clients/openapi-3.4.7.ts rename to core/ledger-client-types/src/generated-clients/openapi-3.4.11.ts index 3aef1a14c..bcebb428d 100644 --- a/core/ledger-client/src/generated-clients/openapi-3.4.7.ts +++ b/core/ledger-client-types/src/generated-clients/openapi-3.4.11.ts @@ -850,6 +850,28 @@ export interface paths { patch?: never trace?: never } + '/v2/contracts/contract-by-id': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * @description Looking up contract data by contract ID. + * This endpoint is experimental / alpha, therefore no backwards compatibility is guaranteed. + * This endpoint must not be used to look up contracts which entered the participant via party replication + * or repair service. + */ + post: operations['postV2ContractsContract-by-id'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } } export type webhooks = Record export interface components { @@ -2077,6 +2099,40 @@ export interface components { GetConnectedSynchronizersResponse: { connectedSynchronizers?: components['schemas']['ConnectedSynchronizer'][] } + /** GetContractRequest */ + GetContractRequest: { + /** + * @description The ID of the contract. + * Must be a valid LedgerString (as described in ``value.proto``). + * Required + */ + contractId: string + /** + * @description The list of querying parties + * The stakeholders of the referenced contract must have an intersection with any of these parties + * to return the result. + * Optional, if no querying_parties specified, all possible contracts could be returned. + */ + queryingParties?: string[] + } + /** GetContractResponse */ + GetContractResponse: { + /** + * @description The representative_package_id will be always set to the contract package ID, therefore this endpoint should + * not be used to lookup contract which entered the participant via party replication or repair service. + * The witnesses field will contain only the querying_parties which are also stakeholders of the contract as well. + * The following fields of the created event cannot be populated, so those should not be used / parsed: + * + * - offset + * - node_id + * - created_event_blob + * - interface_views + * - acs_delta + * + * Required + */ + createdEvent?: components['schemas']['CreatedEvent'] + } /** GetEventsByContractIdRequest */ GetEventsByContractIdRequest: { /** @@ -5588,6 +5644,8 @@ export interface operations { getV2Parties: { parameters: { query?: { + 'identity-provider-id'?: string + 'filter-party'?: string /** @description maximum number of elements in a returned page */ pageSize?: number /** @description token - to continue results from a given page, leave empty to start from the beginning of the list, obtain token from the result of previous page */ @@ -5607,7 +5665,7 @@ export interface operations { 'application/json': components['schemas']['ListKnownPartiesResponse'] } } - /** @description Invalid value for: query parameter pageSize, Invalid value for: query parameter pageToken, Invalid value for: headers */ + /** @description Invalid value for: query parameter identity-provider-id, Invalid value for: query parameter filter-party, Invalid value for: query parameter pageSize, Invalid value for: query parameter pageToken, Invalid value for: headers */ 400: { headers: { [name: string]: unknown @@ -7235,4 +7293,44 @@ export interface operations { } } } + 'postV2ContractsContract-by-id': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['GetContractRequest'] + } + } + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GetContractResponse'] + } + } + /** @description Invalid value for: body, Invalid value for: headers */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'text/plain': string + } + } + default: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['JsCantonError'] + } + } + } + } } diff --git a/core/ledger-client-types/src/index.ts b/core/ledger-client-types/src/index.ts new file mode 100644 index 000000000..3146bc40a --- /dev/null +++ b/core/ledger-client-types/src/index.ts @@ -0,0 +1,7 @@ +// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +export * as v3_3 from './generated-clients/openapi-3.3.0-SNAPSHOT.js' +export * as v3_4 from './generated-clients/openapi-3.4.11.js' +export * from './generated-clients/asyncapi-3.4.11.js' +export * from './utils.js' diff --git a/core/ledger-client-types/src/utils.ts b/core/ledger-client-types/src/utils.ts new file mode 100644 index 000000000..82909bc41 --- /dev/null +++ b/core/ledger-client-types/src/utils.ts @@ -0,0 +1,190 @@ +// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import * as v3_3 from './generated-clients/openapi-3.3.0-SNAPSHOT.js' + +import * as v3_4 from './generated-clients/openapi-3.4.11.js' +import { PartyId } from '@canton-network/core-types' + +type TransactionFilter = Types['TransactionFilter'] +type EventFormat = Types['EventFormat'] +type Types = v3_3.components['schemas'] | v3_4.components['schemas'] +type BaseFilterOptions = { + includeWildcard?: boolean + isMasterUser?: boolean + partyId?: PartyId | undefined +} + +type FilterIdentifiers = + | { + templateIds: string[] | string + interfaceIds?: never + } + | { + interfaceIds: string[] | string + templateIds?: never + } + +type TransactionFilterOptions = BaseFilterOptions & FilterIdentifiers + +type EventFilterOptions = TransactionFilterOptions & { verbose?: boolean } + +export function TransactionFilterBySetup( + options: TransactionFilterOptions +): TransactionFilter { + const { templateIds, interfaceIds, ...baseOptions } = options + return buildFilter( + normalizeToArray(templateIds || []), + normalizeToArray(interfaceIds || []), + baseOptions + ) +} + +export function EventFilterBySetup(options: EventFilterOptions): EventFormat { + const { + templateIds, + interfaceIds, + verbose = false, + ...baseOptions + } = options + return buildFilter( + normalizeToArray(templateIds || []), + normalizeToArray(interfaceIds || []), + baseOptions, + { verbose } + ) +} + +function normalizeToArray(value: T | T[]): T[] { + return Array.isArray(value) ? value : [value] +} + +function createWildcardFilter() { + return { + identifierFilter: { + WildcardFilter: { + value: { + includeCreatedEventBlob: true, + }, + }, + }, + } +} + +function createIdentiferFilter(type: 'Template' | 'Interface', id: string) { + if (type === 'Template') { + return { + identifierFilter: { + TemplateFilter: { + value: { + templateId: id, + includeCreatedEventBlob: true, + }, + }, + }, + } + } else { + return { + identifierFilter: { + InterfaceFilter: { + value: { + interfaceId: id, + includeInterfaceView: true, + includeCreatedEventBlob: true, + }, + }, + }, + } + } +} + +function buildCumulativeFilters( + templateIds: string[], + interfaceIds: string[], + includeWildcard: boolean +) { + if (templateIds.length > 0) { + return [ + ...templateIds.map((templateId) => + createIdentiferFilter('Template', templateId) + ), + ...(includeWildcard ? [createWildcardFilter()] : []), + ] + } else { + return [ + ...interfaceIds.map((interfaceId) => + createIdentiferFilter('Interface', interfaceId) + ), + ...(includeWildcard ? [createWildcardFilter()] : []), + ] + } +} + +function filtersByParty( + party: PartyId, + templateIds: string[], + interfaceIds: string[], + includeWildcard: boolean +): TransactionFilter['filtersByParty'] { + return { + [party]: { + cumulative: buildCumulativeFilters( + templateIds, + interfaceIds, + includeWildcard + ), + }, + } +} + +function filtersForAnyParty( + interfaceNames: string[], + templateIds: string[], + includeWildcard: boolean +): TransactionFilter['filtersForAnyParty'] { + return { + cumulative: buildCumulativeFilters( + templateIds, + interfaceNames, + includeWildcard + ), + } +} + +function buildFilter< + // eslint-disable-next-line @typescript-eslint/no-explicit-any + T extends { filtersByParty?: any; filtersForAnyParty?: any }, +>( + templateIds: string[], + interfaceIds: string[], + options: BaseFilterOptions, + additionalProps?: Partial +): T { + const { isMasterUser = false, partyId, includeWildcard = false } = options + + if (isMasterUser) { + return { + filtersByParty: {}, + filtersForAnyParty: filtersForAnyParty( + templateIds, + interfaceIds, + includeWildcard + ), + ...additionalProps, + } as T + } + + if (!partyId) { + throw new Error('Party must be provided for non-master users') + } + + return { + filtersByParty: filtersByParty( + partyId, + templateIds, + interfaceIds, + includeWildcard + ), + ...additionalProps, + } as T +} diff --git a/core/ledger-client-types/tsconfig.json b/core/ledger-client-types/tsconfig.json new file mode 100644 index 000000000..572eba58e --- /dev/null +++ b/core/ledger-client-types/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.web.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist" + }, + "include": ["src"] +} diff --git a/core/ledger-client-types/tsconfig.types.json b/core/ledger-client-types/tsconfig.types.json new file mode 100644 index 000000000..e522515b7 --- /dev/null +++ b/core/ledger-client-types/tsconfig.types.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.web.json", + "compilerOptions": { + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true, + "rootDir": "./src", + "outDir": "./dist", + "moduleResolution": "bundler", + "noEmit": false, + "composite": false + }, + "include": ["src/**/*.ts", "src/**/*.d.ts"], + "exclude": ["**/*.test.*", "**/*.spec.*", "**/__tests__/**"] +} diff --git a/core/ledger-client-types/tsup.config.ts b/core/ledger-client-types/tsup.config.ts new file mode 100644 index 000000000..1f4074292 --- /dev/null +++ b/core/ledger-client-types/tsup.config.ts @@ -0,0 +1,10 @@ +// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { defineConfig } from 'tsup' +import { base } from '../../tsup.base' + +export default defineConfig({ + ...base, + entry: ['src/index.ts'], +}) diff --git a/core/ledger-client/package.json b/core/ledger-client/package.json index 88601a223..fa859ec72 100644 --- a/core/ledger-client/package.json +++ b/core/ledger-client/package.json @@ -1,6 +1,6 @@ { "name": "@canton-network/core-ledger-client", - "version": "0.27.1", + "version": "0.27.2", "type": "module", "description": "Provides a TypeScript Canton Network ledger client, generated by the OpenAPI spec", "license": "Apache-2.0", @@ -38,6 +38,7 @@ "typescript": "^5.9.3" }, "dependencies": { + "@canton-network/core-ledger-client-types": "workspace:^", "@canton-network/core-ledger-proto": "workspace:^", "@canton-network/core-splice-client": "workspace:^", "@canton-network/core-token-standard": "workspace:^", diff --git a/core/ledger-client/src/index.ts b/core/ledger-client/src/index.ts index b211af71b..45eb5bf3d 100644 --- a/core/ledger-client/src/index.ts +++ b/core/ledger-client/src/index.ts @@ -4,7 +4,6 @@ export * from './token-standard-service.js' export { AmuletService } from './amulet-service.js' export * from './ledger-client.js' -export * from './generated-clients/openapi-3.3.0-SNAPSHOT.js' export * from './acs/acs-container.js' export * from './acs/ws-support.js' export type { @@ -43,9 +42,4 @@ export { defaultRetryableOptions, } from './ledger-api-utils.js' -export * from './web-socket-client.js' -export { - GetUpdatesRequest, - JsGetUpdatesResponse, - CompletionResponse, -} from './generated-clients/asyncapi-3.4.7.js' +export * from '@canton-network/core-ledger-client-types' diff --git a/core/ledger-client/src/ledger-api-utils.ts b/core/ledger-client/src/ledger-api-utils.ts index 971900416..f1444b16a 100644 --- a/core/ledger-client/src/ledger-api-utils.ts +++ b/core/ledger-client/src/ledger-api-utils.ts @@ -13,8 +13,6 @@ import { import { Logger } from '@canton-network/core-types' import { ErrorInfo, RetryInfo } from '@canton-network/core-ledger-proto' -type TransactionFilter = Types['TransactionFilter'] -type EventFormat = Types['EventFormat'] type CreatedEvent = Types['CreatedEvent'] type ExercisedEvent = Types['ExercisedEvent'] type ArchivedEvent = Types['ArchivedEvent'] @@ -23,186 +21,6 @@ type Completion = Types['Completion']['value'] export type JSContractEntry = Types['JsContractEntry'] export type JsCantonError = Types['JsCantonError'] -type BaseFilterOptions = { - includeWildcard?: boolean - isMasterUser?: boolean - partyId?: PartyId | undefined -} - -type FilterIdentifiers = - | { - templateIds: string[] | string - interfaceIds?: never - } - | { - interfaceIds: string[] | string - templateIds?: never - } - -type TransactionFilterOptions = BaseFilterOptions & FilterIdentifiers - -type EventFilterOptions = TransactionFilterOptions & { verbose?: boolean } - -function createIdentiferFilter(type: 'Template' | 'Interface', id: string) { - if (type === 'Template') { - return { - identifierFilter: { - TemplateFilter: { - value: { - templateId: id, - includeCreatedEventBlob: true, - }, - }, - }, - } - } else { - return { - identifierFilter: { - InterfaceFilter: { - value: { - interfaceId: id, - includeInterfaceView: true, - includeCreatedEventBlob: true, - }, - }, - }, - } - } -} - -function createWildcardFilter() { - return { - identifierFilter: { - WildcardFilter: { - value: { - includeCreatedEventBlob: true, - }, - }, - }, - } -} - -function buildCumulativeFilters( - templateIds: string[], - interfaceIds: string[], - includeWildcard: boolean -) { - if (templateIds.length > 0) { - return [ - ...templateIds.map((templateId) => - createIdentiferFilter('Template', templateId) - ), - ...(includeWildcard ? [createWildcardFilter()] : []), - ] - } else { - return [ - ...interfaceIds.map((interfaceId) => - createIdentiferFilter('Interface', interfaceId) - ), - ...(includeWildcard ? [createWildcardFilter()] : []), - ] - } -} - -function buildFilter< - // eslint-disable-next-line @typescript-eslint/no-explicit-any - T extends { filtersByParty?: any; filtersForAnyParty?: any }, ->( - templateIds: string[], - interfaceIds: string[], - options: BaseFilterOptions, - additionalProps?: Partial -): T { - const { isMasterUser = false, partyId, includeWildcard = false } = options - - if (isMasterUser) { - return { - filtersByParty: {}, - filtersForAnyParty: filtersForAnyParty( - templateIds, - interfaceIds, - includeWildcard - ), - ...additionalProps, - } as T - } - - if (!partyId) { - throw new Error('Party must be provided for non-master users') - } - - return { - filtersByParty: filtersByParty( - partyId, - templateIds, - interfaceIds, - includeWildcard - ), - ...additionalProps, - } as T -} - -export function TransactionFilterBySetup( - options: TransactionFilterOptions -): TransactionFilter { - const { templateIds, interfaceIds, ...baseOptions } = options - return buildFilter( - normalizeToArray(templateIds || []), - normalizeToArray(interfaceIds || []), - baseOptions - ) -} - -export function EventFilterBySetup(options: EventFilterOptions): EventFormat { - const { - templateIds, - interfaceIds, - verbose = false, - ...baseOptions - } = options - return buildFilter( - normalizeToArray(templateIds || []), - normalizeToArray(interfaceIds || []), - baseOptions, - { verbose } - ) -} - -function filtersByParty( - party: PartyId, - templateIds: string[], - interfaceIds: string[], - includeWildcard: boolean -): TransactionFilter['filtersByParty'] { - return { - [party]: { - cumulative: buildCumulativeFilters( - templateIds, - interfaceIds, - includeWildcard - ), - }, - } -} - -function filtersForAnyParty( - interfaceNames: string[], - templateIds: string[], - includeWildcard: boolean -): TransactionFilter['filtersForAnyParty'] { - return { - cumulative: buildCumulativeFilters( - templateIds, - interfaceNames, - includeWildcard - ), - } -} - -function normalizeToArray(value: T | T[]): T[] { - return Array.isArray(value) ? value : [value] -} - export function hasInterface( interfaceId: string, event: ExercisedEvent | ArchivedEvent diff --git a/core/ledger-client/src/ledger-client.ts b/core/ledger-client/src/ledger-client.ts index bbfe5e458..c7f6e0dbf 100644 --- a/core/ledger-client/src/ledger-client.ts +++ b/core/ledger-client/src/ledger-client.ts @@ -1,9 +1,7 @@ // Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -import * as v3_3 from './generated-clients/openapi-3.3.0-SNAPSHOT.js' - -import * as v3_4 from './generated-clients/openapi-3.4.7.js' +import { v3_3, v3_4 } from '@canton-network/core-ledger-client-types' import createClient, { Client, FetchOptions } from 'openapi-fetch' import { Logger } from 'pino' import { PartyId } from '@canton-network/core-types' @@ -17,6 +15,10 @@ import { import { ACSHelper, AcsHelperOptions } from './acs/acs-helper.js' import { SharedACSCache } from './acs/acs-shared-cache.js' import { AccessTokenProvider } from '@canton-network/core-wallet-auth' + +export type UserSchema = + | v3_3.components['schemas']['User'] + | v3_4.components['schemas']['User'] export const supportedVersions = ['3.3', '3.4'] as const export type SupportedVersions = (typeof supportedVersions)[number] @@ -541,7 +543,7 @@ export class LedgerClient { } /* - if limit is provided, this function performs a one-time query + if limit is provided, this function performs a one-time query. Automatically splits into multiple `/v2/updates` calls with `continueUntilCompletion` on. if limit is omitted, results may be served from the ACS cache current cache design doesn't support limiting queries because updates/deltas for the acs at offset x will be incorrect TODO: expose query mode vs subscribe mode to call queryActiveContracts vs subscribeActiveContracts @@ -553,8 +555,16 @@ export class LedgerClient { filterByParty?: boolean interfaceIds?: string[] limit?: number + continueUntilCompletion?: boolean }): Promise> { - const { offset, templateIds, parties, interfaceIds, limit } = options + const { + offset, + templateIds, + parties, + interfaceIds, + limit, + continueUntilCompletion, + } = options const hasLimit = typeof limit === 'number' @@ -562,13 +572,16 @@ export class LedgerClient { if (hasLimit) { const filter = this.buildActiveContractFilter(options) + if (continueUntilCompletion) + return await this.fetchActiveContractsUntilComplete( + filter, + limit + ) return await this.postWithRetry( '/v2/state/active-contracts', filter, defaultRetryableOptions, - { - query: limit ? { limit: limit.toString() } : {}, - } + { query: { limit: limit.toString() } } ) } @@ -604,6 +617,79 @@ export class LedgerClient { ) } + /** + * Fetches active contracts by splitting requests into multiple `/v2/updates` calls. + * Should only be used when the number of contracts exceeds http-list-max-elements-limit (200 by default). + * For limits at or below http-list-max-elements-limit, use a single `/v2/state/active-contracts` call instead. + * @param activeContractsArgs The request parameters for active contracts query + * @returns A promise that resolves to an array of active contract responses + * @private + */ + private async fetchActiveContractsUntilComplete( + activeContractsArgs: PostRequest<'/v2/state/active-contracts'>, + limit: number + ): Promise> { + const result = [] + const ledgerEnd = await this.getWithRetry('/v2/state/ledger-end') + + const bodyRequest: PostRequest<'/v2/updates'> = { + beginExclusive: 0, + endInclusive: ledgerEnd.offset, + verbose: false, + } + if (activeContractsArgs.filter) + bodyRequest.filter = activeContractsArgs.filter + let currentOffset = 0 + while (currentOffset < ledgerEnd.offset) { + bodyRequest.beginExclusive = currentOffset + const newResults: Array = ( + await this.postWithRetry( + '/v2/updates', + bodyRequest, + defaultRetryableOptions, + { + query: { limit: limit.toString() }, + } + ) + ) + .filter(({ update }) => 'Transaction' in update) + .map(({ update }) => { + if ('Transaction' in update) { + return update.Transaction.value + } + throw new Error('Expected Transaction update') + }) + .map((data) => { + const createdEvent = data.events?.find( + (event: unknown) => + typeof event === 'object' && + event !== null && + 'CreatedEvent' in event + ) + if (!createdEvent || !('CreatedEvent' in createdEvent)) { + throw new Error( + 'CreatedEvent not found in transaction events' + ) + } + currentOffset = Math.max(currentOffset, data.offset) + return { + workflowId: data.workflowId, + contractEntry: { + JsActiveContract: { + synchronizerId: data.synchronizerId, + createdEvent: createdEvent.CreatedEvent, + reassignmentCounter: data.offset, + }, + }, + } + }) + + result.push(...newResults) + if (!newResults.length) currentOffset++ + } + return result + } + private buildActiveContractFilter(options: { offset: number templateIds?: string[] diff --git a/core/ledger-client/src/token-standard-service.ts b/core/ledger-client/src/token-standard-service.ts index d23d383a7..41c8914a9 100644 --- a/core/ledger-client/src/token-standard-service.ts +++ b/core/ledger-client/src/token-standard-service.ts @@ -23,13 +23,11 @@ import { ContractId, Beneficiaries, } from '@canton-network/core-token-standard' +import { EventFilterBySetup } from '@canton-network/core-ledger-client-types' import { Logger, PartyId } from '@canton-network/core-types' import { LedgerClient } from './ledger-client.js' import { TokenStandardTransactionInterfaces } from './constants.js' -import { - ensureInterfaceViewIsPresent, - EventFilterBySetup, -} from './ledger-api-utils.js' +import { ensureInterfaceViewIsPresent } from './ledger-api-utils.js' import { TransactionParser } from './txparse/parser.js' import { PrettyContract, @@ -49,7 +47,7 @@ export type DisclosedContract = Types['DisclosedContract'] const EMPTY_META: Metadata = { values: {} } type JsGetActiveContractsResponse = Types['JsGetActiveContractsResponse'] -export type JsGetUpdatesResponse = Types['JsGetUpdatesResponse'] +type JsGetUpdatesResponse = Types['JsGetUpdatesResponse'] type JsGetTransactionResponse = Types['JsGetTransactionResponse'] type OffsetCheckpoint2 = Types['OffsetCheckpoint2'] type JsTransaction = Types['JsTransaction'] @@ -204,7 +202,8 @@ export class CoreService { interfaceId: string, partyId?: PartyId, limit?: number, - offset?: number + offset?: number, + continueUntilCompletion?: boolean ): Promise[]> { try { const ledgerEnd = @@ -212,17 +211,14 @@ export class CoreService { (await this.ledgerClient.getWithRetry('/v2/state/ledger-end')) .offset - const options: { - offset: number - interfaceIds: string[] - parties: PartyId[] - filterByParty: boolean - limit?: number - } = { + const options: Parameters< + typeof this.ledgerClient.activeContracts + >[0] = { offset: ledgerEnd, interfaceIds: [interfaceId], parties: [partyId!], filterByParty: true, + continueUntilCompletion: Boolean(continueUntilCompletion), } if (limit !== undefined) { @@ -1331,13 +1327,15 @@ export class TokenStandardService { interfaceId: string, partyId?: PartyId, limit?: number, - offset?: number + offset?: number, + continueUntilCompletion?: boolean ): Promise[]> { return this.core.listContractsByInterface( interfaceId, partyId, limit, - offset + offset, + continueUntilCompletion ) } diff --git a/core/ledger-client/src/txparse/parser.test.ts b/core/ledger-client/src/txparse/parser.test.ts index 2fa69d0a2..d7d11090a 100644 --- a/core/ledger-client/src/txparse/parser.test.ts +++ b/core/ledger-client/src/txparse/parser.test.ts @@ -7,19 +7,23 @@ import { TransactionParser } from './parser.js' import type { PrettyTransactions, Transaction } from './types.js' import eventsByContractIdResponses from './test-data/mock/eventsByContractIdResponses.js' import type { LedgerClient } from '../ledger-client' -import { components } from '../generated-clients/openapi-3.3.0-SNAPSHOT.js' +import { + v3_3, + JsGetUpdatesResponse, +} from '@canton-network/core-ledger-client-types' import * as fs from 'fs' import { dirname } from 'path' import { fileURLToPath } from 'url' -import { CoreService, JsGetUpdatesResponse } from '../token-standard-service.js' +import { CoreService } from '../token-standard-service.js' import { ScanProxyClient } from '@canton-network/core-splice-client' import { AccessTokenProvider } from '@canton-network/core-wallet-auth' -type JsTransaction = components['schemas']['JsTransaction'] +//TODO: should this be updated to use the v3_4 types as well? +type JsTransaction = v3_3.components['schemas']['JsTransaction'] type JsGetEventsByContractIdResponse = - components['schemas']['JsGetEventsByContractIdResponse'] + v3_3.components['schemas']['JsGetEventsByContractIdResponse'] -type CreatedEvent = components['schemas']['CreatedEvent'] +type CreatedEvent = v3_3.components['schemas']['CreatedEvent'] const EVENTS_BY_CID_PATH = '/v2/events/events-by-contract-id' as const diff --git a/core/ledger-client/src/txparse/parser.ts b/core/ledger-client/src/txparse/parser.ts index e455fe886..437f4924a 100644 --- a/core/ledger-client/src/txparse/parser.ts +++ b/core/ledger-client/src/txparse/parser.ts @@ -10,7 +10,6 @@ import { hasInterface, mergeMetas, removeParsedMetaKeys, - EventFilterBySetup, } from '../ledger-api-utils.js' import { BurnedMetaKey, @@ -33,7 +32,10 @@ import { } from './types.js' import { InstrumentMap } from './instrumentmap.js' -import { components } from '../generated-clients/openapi-3.3.0-SNAPSHOT' +import { + v3_3, + EventFilterBySetup, +} from '@canton-network/core-ledger-client-types' import { LedgerClient } from '../ledger-client' import BigNumber from 'bignumber.js' import { PartyId } from '@canton-network/core-types' @@ -42,13 +44,13 @@ import { TRANSFER_INSTRUCTION_INTERFACE_ID, } from '@canton-network/core-token-standard' -type ArchivedEvent = components['schemas']['ArchivedEvent'] -type CreatedEvent = components['schemas']['CreatedEvent'] -type ExercisedEvent = components['schemas']['ExercisedEvent'] -type Event = components['schemas']['Event'] -type JsTransaction = components['schemas']['JsTransaction'] +type ArchivedEvent = v3_3.components['schemas']['ArchivedEvent'] +type CreatedEvent = v3_3.components['schemas']['CreatedEvent'] +type ExercisedEvent = v3_3.components['schemas']['ExercisedEvent'] +type Event = v3_3.components['schemas']['Event'] +type JsTransaction = v3_3.components['schemas']['JsTransaction'] type JsGetEventsByContractIdResponse = - components['schemas']['JsGetEventsByContractIdResponse'] + v3_3.components['schemas']['JsGetEventsByContractIdResponse'] function currentStatusFromChoiceOrResult( choice?: string | undefined, diff --git a/core/ledger-client/src/txparse/types.ts b/core/ledger-client/src/txparse/types.ts index 0e2b0e634..c93086b46 100644 --- a/core/ledger-client/src/txparse/types.ts +++ b/core/ledger-client/src/txparse/types.ts @@ -2,12 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 /* eslint-disable @typescript-eslint/no-explicit-any */ -import { components } from '../generated-clients/openapi-3.3.0-SNAPSHOT' +import { v3_3 } from '@canton-network/core-ledger-client-types' import { Metadata } from '@canton-network/core-token-standard' -export type ViewValue = components['schemas']['JsInterfaceView']['viewValue'] // unknown | undefined -export type JsActiveContract = components['schemas']['JsActiveContract'] - +export type ViewValue = + v3_3.components['schemas']['JsInterfaceView']['viewValue'] // unknown | undefined +export type JsActiveContract = v3_3.components['schemas']['JsActiveContract'] export interface Transaction { updateId: string offset: number diff --git a/core/signing-internal/package.json b/core/signing-internal/package.json index c3df4cf80..90da211f4 100644 --- a/core/signing-internal/package.json +++ b/core/signing-internal/package.json @@ -1,6 +1,6 @@ { "name": "@canton-network/core-signing-internal", - "version": "0.22.1", + "version": "0.22.2", "type": "module", "description": "Wallet Gateway driver for offline Ed25519 keypairs", "license": "Apache-2.0", diff --git a/core/signing-participant/package.json b/core/signing-participant/package.json index 5779bcba5..b26a69acb 100644 --- a/core/signing-participant/package.json +++ b/core/signing-participant/package.json @@ -1,6 +1,6 @@ { "name": "@canton-network/core-signing-participant", - "version": "0.22.1", + "version": "0.22.2", "packageManager": "yarn@4.9.4", "type": "module", "description": "Wallet Gateway driver for Canton participant internal parties", diff --git a/core/signing-store-sql/package.json b/core/signing-store-sql/package.json index d5283c4a1..d61059103 100644 --- a/core/signing-store-sql/package.json +++ b/core/signing-store-sql/package.json @@ -1,6 +1,6 @@ { "name": "@canton-network/core-signing-store-sql", - "version": "0.23.1", + "version": "0.23.2", "type": "module", "description": "SQL implementation of the Store API", "license": "Apache-2.0", diff --git a/core/splice-provider/package.json b/core/splice-provider/package.json index ac94c78fa..b6360a71c 100644 --- a/core/splice-provider/package.json +++ b/core/splice-provider/package.json @@ -1,6 +1,6 @@ { "name": "@canton-network/core-splice-provider", - "version": "0.23.1", + "version": "0.24.0", "type": "module", "description": "A JavaScript Splice Provider API (EIP-1193 compliant).", "license": "Apache-2.0", diff --git a/core/wallet-dapp-remote-rpc-client/package.json b/core/wallet-dapp-remote-rpc-client/package.json index fd0fe0860..0fa6395ed 100644 --- a/core/wallet-dapp-remote-rpc-client/package.json +++ b/core/wallet-dapp-remote-rpc-client/package.json @@ -1,6 +1,6 @@ { "name": "@canton-network/core-wallet-dapp-remote-rpc-client", - "version": "0.16.1", + "version": "0.17.0", "type": "module", "description": "TypeScript client generated by OpenRPC", "license": "Apache-2.0", diff --git a/core/wallet-dapp-remote-rpc-client/src/index.ts b/core/wallet-dapp-remote-rpc-client/src/index.ts index 9c71f8e1f..fd072adfd 100644 --- a/core/wallet-dapp-remote-rpc-client/src/index.ts +++ b/core/wallet-dapp-remote-rpc-client/src/index.ts @@ -96,19 +96,25 @@ export type Resource = string export type Body = string /** * - * The unique identifier of the Wallet Gateway. + * The unique identifier of the Provider. * */ export type Id = string /** * - * The type of client that implements the Wallet Gateway. + * The version of the Provider. * */ -export type ClientType = 'browser' | 'desktop' | 'mobile' | 'remote' +export type Version = string /** * - * The URL of the Wallet Gateway. + * The type of client that implements the Provider. + * + */ +export type ProviderType = 'browser' | 'desktop' | 'mobile' | 'remote' +/** + * + * The URL of the Wallet Provider. * */ export type Url = string @@ -120,12 +126,13 @@ export type Url = string export type UserUrl = string /** * - * Represents a Wallet Gateway. + * Represents a Provider. * */ -export interface KernelInfo { +export interface Provider { id: Id - clientType: ClientType + version?: Version + providerType?: ProviderType url?: Url userUrl?: UserUrl [k: string]: any @@ -136,6 +143,12 @@ export interface KernelInfo { * */ export type IsConnected = boolean +/** + * + * Reason for the wallet state, e.g., 'no signing provider matched'. + * + */ +export type Reason = string /** * * Whether or not a connection to a network is established. @@ -148,6 +161,13 @@ export type IsNetworkConnected = boolean * */ export type NetworkReason = string +export interface ConnectResult { + isConnected: IsConnected + reason?: Reason + isNetworkConnected: IsNetworkConnected + networkReason?: NetworkReason + [k: string]: any +} /** * * The network ID the wallet corresponds to. @@ -159,16 +179,13 @@ export type NetworkId = string * The base URL of the ledger API. * */ -export type BaseUrl = string +export type LedgerApiUrl = string /** * - * Ledger API configuration. + * JWT authentication token. * */ -export interface LedgerApiConfig { - baseUrl: BaseUrl - [k: string]: any -} +export type AccessToken = string /** * * Network information, if connected to a network. @@ -176,15 +193,10 @@ export interface LedgerApiConfig { */ export interface Network { networkId: NetworkId - ledgerApi?: LedgerApiConfig + ledgerApi?: LedgerApiUrl + accessToken?: AccessToken [k: string]: any } -/** - * - * JWT authentication token. - * - */ -export type AccessToken = string /** * * The user identifier. @@ -201,19 +213,6 @@ export interface Session { userId: UserId [k: string]: any } -export interface StatusEvent { - kernel: KernelInfo - isConnected: IsConnected - isNetworkConnected: IsNetworkConnected - networkReason?: NetworkReason - network?: Network - session?: Session - [k: string]: any -} -export interface ConnectResult { - userUrl: UserUrl - [k: string]: any -} /** * * The signature of the transaction. @@ -281,12 +280,6 @@ export type TopologyTransactions = string * */ export type Disabled = boolean -/** - * - * Reason for the wallet state, e.g., 'no signing provider matched'. - * - */ -export type Reason = string /** * * Structure representing a wallet @@ -436,7 +429,13 @@ export interface LedgerApiParams { body?: Body [k: string]: any } -export type StatusEventAsync = StatusEvent & ConnectResult +export interface StatusEvent { + provider: Provider + connection: ConnectResult + network?: Network + session?: Session + [k: string]: any +} /** * * Represents a null value, used in responses where no data is returned. @@ -494,7 +493,7 @@ export type TxChangedEvent = */ export type Status = () => Promise -export type Connect = () => Promise +export type Connect = () => Promise export type Disconnect = () => Promise export type GetActiveNetwork = () => Promise export type PrepareExecute = ( diff --git a/core/wallet-dapp-remote-rpc-client/src/openrpc.json b/core/wallet-dapp-remote-rpc-client/src/openrpc.json index 1b88d8929..df9013fca 100644 --- a/core/wallet-dapp-remote-rpc-client/src/openrpc.json +++ b/core/wallet-dapp-remote-rpc-client/src/openrpc.json @@ -3,7 +3,7 @@ "info": { "title": "Splice Wallet JSON-RPC Remote dApp API", "version": "0.1.0", - "description": "An OpenRPC specification for remotely hosted Wallet Gateways. Due to the remote nature, an implementing provider must bridge certain functionality on the client-side to satisfy the general dApp API spec." + "description": "An OpenRPC specification for remotely hosted Wallet Providers. Due to the remote nature, an implementing provider must bridge certain functionality on the client-side to satisfy the general dApp API spec." }, "methods": [ { @@ -15,7 +15,7 @@ "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/StatusEvent" } }, - "description": "Returns the current status of the wallet gateway session." + "description": "Returns the current status of the wallet provider session." }, { "name": "connect", @@ -23,25 +23,10 @@ "result": { "name": "result", "schema": { - "title": "StatusEventAsync", - "allOf": [ - { - "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/StatusEvent" - }, - { - "type": "object", - "title": "ConnectResult", - "properties": { - "userUrl": { - "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/UserUrl" - } - }, - "required": ["userUrl"] - } - ] + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/ConnectResult" } }, - "description": "Ensures ledger connectivity and returns the connected network information along with the user access token. NetworkId should follow CAIP-2 and represent the synchronizerId." + "description": "Ensures ledger connectivity and returns the connected network information." }, { "name": "disconnect", diff --git a/core/wallet-dapp-rpc-client/package.json b/core/wallet-dapp-rpc-client/package.json index 91dddff80..1b8dd6471 100644 --- a/core/wallet-dapp-rpc-client/package.json +++ b/core/wallet-dapp-rpc-client/package.json @@ -1,6 +1,6 @@ { "name": "@canton-network/core-wallet-dapp-rpc-client", - "version": "0.22.1", + "version": "0.23.0", "type": "module", "description": "TypeScript client generated by OpenRPC", "license": "Apache-2.0", diff --git a/core/wallet-dapp-rpc-client/src/index.ts b/core/wallet-dapp-rpc-client/src/index.ts index 97f3d8c42..fda623d36 100644 --- a/core/wallet-dapp-rpc-client/src/index.ts +++ b/core/wallet-dapp-rpc-client/src/index.ts @@ -96,19 +96,25 @@ export type Resource = string export type Body = string /** * - * The unique identifier of the Wallet Gateway. + * The unique identifier of the Provider. * */ export type Id = string /** * - * The type of client that implements the Wallet Gateway. + * The version of the Provider. * */ -export type ClientType = 'browser' | 'desktop' | 'mobile' | 'remote' +export type Version = string /** * - * The URL of the Wallet Gateway. + * The type of client that implements the Provider. + * + */ +export type ProviderType = 'browser' | 'desktop' | 'mobile' | 'remote' +/** + * + * The URL of the Wallet Provider. * */ export type Url = string @@ -120,12 +126,13 @@ export type Url = string export type UserUrl = string /** * - * Represents a Wallet Gateway. + * Represents a Provider. * */ -export interface KernelInfo { +export interface Provider { id: Id - clientType: ClientType + version?: Version + providerType?: ProviderType url?: Url userUrl?: UserUrl [k: string]: any @@ -136,6 +143,12 @@ export interface KernelInfo { * */ export type IsConnected = boolean +/** + * + * Reason for the wallet state, e.g., 'no signing provider matched'. + * + */ +export type Reason = string /** * * Whether or not a connection to a network is established. @@ -148,6 +161,13 @@ export type IsNetworkConnected = boolean * */ export type NetworkReason = string +export interface ConnectResult { + isConnected: IsConnected + reason?: Reason + isNetworkConnected: IsNetworkConnected + networkReason?: NetworkReason + [k: string]: any +} /** * * The network ID the wallet corresponds to. @@ -159,16 +179,13 @@ export type NetworkId = string * The base URL of the ledger API. * */ -export type BaseUrl = string +export type LedgerApiUrl = string /** * - * Ledger API configuration. + * JWT authentication token. * */ -export interface LedgerApiConfig { - baseUrl: BaseUrl - [k: string]: any -} +export type AccessToken = string /** * * Network information, if connected to a network. @@ -176,15 +193,10 @@ export interface LedgerApiConfig { */ export interface Network { networkId: NetworkId - ledgerApi?: LedgerApiConfig + ledgerApi?: LedgerApiUrl + accessToken?: AccessToken [k: string]: any } -/** - * - * JWT authentication token. - * - */ -export type AccessToken = string /** * * The user identifier. @@ -300,12 +312,6 @@ export type TopologyTransactions = string * */ export type Disabled = boolean -/** - * - * Reason for the wallet state, e.g., 'no signing provider matched'. - * - */ -export type Reason = string /** * * Structure representing a wallet @@ -424,10 +430,8 @@ export interface LedgerApiParams { [k: string]: any } export interface StatusEvent { - kernel: KernelInfo - isConnected: IsConnected - isNetworkConnected: IsNetworkConnected - networkReason?: NetworkReason + provider: Provider + connection: ConnectResult network?: Network session?: Session [k: string]: any @@ -489,7 +493,7 @@ export type TxChangedEvent = */ export type Status = () => Promise -export type Connect = () => Promise +export type Connect = () => Promise export type Disconnect = () => Promise export type GetActiveNetwork = () => Promise export type PrepareExecute = (params: PrepareExecuteParams) => Promise diff --git a/core/wallet-dapp-rpc-client/src/openrpc.json b/core/wallet-dapp-rpc-client/src/openrpc.json index 8a59bb8b8..ede056fd5 100644 --- a/core/wallet-dapp-rpc-client/src/openrpc.json +++ b/core/wallet-dapp-rpc-client/src/openrpc.json @@ -3,7 +3,7 @@ "info": { "title": "Splice Wallet JSON-RPC dApp API", "version": "0.5.0", - "description": "An OpenRPC specification for the dapp to interact with a Wallet Gateway." + "description": "An OpenRPC specification for the dapp to interact with a Wallet Provider." }, "methods": [ { @@ -15,7 +15,7 @@ "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/StatusEvent" } }, - "description": "Returns the current status of the wallet gateway session." + "description": "Returns the current status of the wallet provider session." }, { "name": "connect", @@ -23,10 +23,10 @@ "result": { "name": "result", "schema": { - "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/StatusEvent" + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/ConnectResult" } }, - "description": "Ensures ledger connectivity and returns the connected network information along with the user access token. Network ID should follow CAIP-2 and represent the synchronizerId." + "description": "Ensures ledger connectivity and returns the connected network information along with the session information." }, { "name": "disconnect", @@ -37,7 +37,7 @@ "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/Null" } }, - "description": "Invoke a disconnect of the wallet gateway session." + "description": "Invoke a disconnect of the wallet provider session." }, { "name": "getActiveNetwork", @@ -183,26 +183,31 @@ "type": "null", "description": "Represents a null value, used in responses where no data is returned." }, - "KernelInfo": { - "title": "KernelInfo", + "Provider": { + "title": "Provider", "type": "object", - "description": "Represents a Wallet Gateway.", + "description": "Represents a Provider.", "properties": { "id": { "title": "id", "type": "string", - "description": "The unique identifier of the Wallet Gateway." + "description": "The unique identifier of the Provider." + }, + "version": { + "title": "version", + "type": "string", + "description": "The version of the Provider." }, - "clientType": { - "title": "clientType", + "providerType": { + "title": "providerType", "type": "string", "enum": ["browser", "desktop", "mobile", "remote"], - "description": "The type of client that implements the Wallet Gateway." + "description": "The type of client that implements the Provider." }, "url": { "title": "url", "type": "string", - "description": "The URL of the Wallet Gateway." + "description": "The URL of the Wallet Provider." }, "userUrl": { "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/UserUrl" @@ -512,18 +517,20 @@ } ] }, - "StatusEvent": { - "title": "StatusEvent", + "ConnectResult": { + "title": "ConnectResult", "type": "object", "properties": { - "kernel": { - "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/KernelInfo" - }, "isConnected": { "title": "isConnected", "type": "boolean", "description": "Whether or not the user is authenticated with the Wallet." }, + "reason": { + "title": "reason", + "type": "string", + "description": "The reason why the user is not connected to the Wallet." + }, "isNetworkConnected": { "title": "isNetworkConnected", "type": "boolean", @@ -533,30 +540,28 @@ "title": "networkReason", "type": "string", "description": "If not connected to a network, the reason why." + } + }, + "required": ["isConnected", "isNetworkConnected"] + }, + "StatusEvent": { + "title": "StatusEvent", + "type": "object", + "properties": { + "provider": { + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/Provider" + }, + "connection": { + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/ConnectResult" }, "network": { "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/Network" }, "session": { - "title": "session", - "type": "object", - "description": "Session information, if authenticated.", - "properties": { - "accessToken": { - "title": "accessToken", - "type": "string", - "description": "JWT authentication token." - }, - "userId": { - "title": "userId", - "type": "string", - "description": "The user identifier." - } - }, - "required": ["accessToken", "userId"] + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/Session" } }, - "required": ["kernel", "isConnected", "isNetworkConnected"] + "required": ["provider", "connection"] }, "SignMessageRequest": { "title": "SignMessageRequest", @@ -595,21 +600,37 @@ "description": "A CAIP-2 compliant chain ID, e.g. 'canton:da-mainnet'." }, "ledgerApi": { - "title": "LedgerApiConfig", - "type": "object", - "description": "Ledger API configuration.", - "properties": { - "baseUrl": { - "title": "baseUrl", - "type": "string", - "format": "uri", - "description": "The base URL of the ledger API." - } - }, - "required": ["baseUrl"] + "title": "ledgerApiUrl", + "type": "string", + "description": "The base URL of the ledger API.", + "format": "uri" + }, + "accessToken": { + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/AccessToken" } }, "required": ["networkId"] + }, + "AccessToken": { + "title": "accessToken", + "type": "string", + "description": "JWT authentication token." + }, + "Session": { + "title": "session", + "type": "object", + "description": "Session information, if authenticated.", + "properties": { + "accessToken": { + "$ref": "api-specs/openrpc-dapp-api.json#/components/schemas/AccessToken" + }, + "userId": { + "title": "userId", + "type": "string", + "description": "The user identifier." + } + }, + "required": ["accessToken", "userId"] } } } diff --git a/core/wallet-store-inmemory/package.json b/core/wallet-store-inmemory/package.json index 3bc7741f2..34cc0a769 100644 --- a/core/wallet-store-inmemory/package.json +++ b/core/wallet-store-inmemory/package.json @@ -1,6 +1,6 @@ { "name": "@canton-network/core-wallet-store-inmemory", - "version": "0.23.1", + "version": "0.23.2", "type": "module", "description": "In-memory implementation of the Store API", "author": "Marc Juchli ", diff --git a/core/wallet-store-sql/package.json b/core/wallet-store-sql/package.json index 70bd0f131..7150ea26a 100644 --- a/core/wallet-store-sql/package.json +++ b/core/wallet-store-sql/package.json @@ -1,6 +1,6 @@ { "name": "@canton-network/core-wallet-store-sql", - "version": "0.22.1", + "version": "0.22.2", "type": "module", "description": "SQL implementation of the Store API", "license": "Apache-2.0", diff --git a/core/wallet-test-utils/package.json b/core/wallet-test-utils/package.json index 58865702a..743396c67 100644 --- a/core/wallet-test-utils/package.json +++ b/core/wallet-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@canton-network/core-wallet-test-utils", "private": true, - "version": "0.3.1", + "version": "0.3.2", "type": "module", "description": "Utilities for writing (E2E) tests for the wallet gateway", "main": "dist/index.cjs", diff --git a/core/wallet-test-utils/src/wallet-gateway.ts b/core/wallet-test-utils/src/wallet-gateway.ts index b581b624a..230ecb408 100644 --- a/core/wallet-test-utils/src/wallet-gateway.ts +++ b/core/wallet-test-utils/src/wallet-gateway.ts @@ -165,6 +165,9 @@ export class WalletGateway { await (await this.popup()) .getByRole('button', { name: 'Create' }) .click() + await expect( + (await this.popup()).getByRole('button', { name: 'Create' }) + ).toBeEnabled() await (await this.popup()) .getByRole('button', { name: 'Close' }) .click() @@ -203,4 +206,98 @@ export class WalletGateway { ).toBeVisible() return { commandId } } + + async reconnect(args: { + network: 'LocalNet' | 'Local (OAuth IDP)' + customURL?: string + }): Promise { + const connectButton = this.connectButton(this.dappPage) + await expect(connectButton).toBeVisible() + + const discoverPopupPromise = this.dappPage.waitForEvent('popup') + await connectButton.click() + const popup = await discoverPopupPromise + + if (args.customURL !== undefined) { + await popup + .getByRole('listitem') + .filter({ hasText: 'Custom url' }) + .click() + await popup + .getByRole('textbox', { name: 'RPC URL' }) + .fill(args.customURL as string) + } + + const allConnectButtons = popup.locator('button').filter({ + hasText: 'Connect', + }) + const buttonCount = await allConnectButtons.count() + + let clicked = false + for (let i = 0; i < buttonCount; i++) { + const button = allConnectButtons.nth(i) + const hasPreviouslyConnectedAttr = + (await button.getAttribute('data-previously-connected')) === + 'true' + if (!hasPreviouslyConnectedAttr) { + await button.click() + clicked = true + break + } + } + + if (!clicked) { + // Fallback to first Connect button if no main button found + await allConnectButtons.first().click() + } + + const selectNetwork = popup.locator('select#network') + const networkOption = await selectNetwork + .locator('option') + .filter({ hasText: args.network }) + .first() + .getAttribute('value') + await selectNetwork.selectOption(networkOption) + const confirmConnectButton = popup.getByRole('button', { + name: 'Connect', + }) + await confirmConnectButton.click() + await expect(confirmConnectButton).not.toBeVisible() + } + + async logoutFromPopup(): Promise { + const popup = await this.popup() + await popup.getByRole('button', { name: 'Toggle menu' }).click() + await popup.locator('button').filter({ hasText: 'Logout' }).click() + await popup.waitForEvent('close', { timeout: 5000 }) + this._popup = undefined + } + + async closePopup(): Promise { + const popup = await this.popup() + await popup.close() + this._popup = undefined + } + + async isPopupOpen(): Promise { + try { + const popup = await this.popup() + return popup && !popup.isClosed() + } catch { + return false + } + } + + async waitForPopupClosed(): Promise { + if (this._popup) { + await this._popup.waitForEvent('close', { timeout: 5000 }) + this._popup = undefined + } + } + + async waitForPopupUrl(expectedUrl: string | RegExp): Promise { + const popup = await this.popup() + + return popup.waitForURL(expectedUrl, { timeout: 5000 }) + } } diff --git a/core/wallet-ui-components/src/components/discovery.ts b/core/wallet-ui-components/src/components/discovery.ts index 24b7d98ab..b6e16c00c 100644 --- a/core/wallet-ui-components/src/components/discovery.ts +++ b/core/wallet-ui-components/src/components/discovery.ts @@ -211,7 +211,8 @@ export class Discovery extends HTMLElement { private renderKernelOption( kernel: KernelType, - onClear: undefined | (() => void) = undefined + onClear: undefined | (() => void) = undefined, + isPreviouslyConnected: boolean = false ) { const div = this.mkElement('div', '', { class: 'kernel d-flex justify-content-space-between align-items-center flex-wrap mb-3', @@ -221,6 +222,9 @@ export class Discovery extends HTMLElement { class: 'btn btn-primary', type: 'button', ['data-tooltip']: kernel.rpcUrl, + ['data-previously-connected']: isPreviouslyConnected + ? 'true' + : 'false', }) const nameWrapper = this.mkElement('div', '', { @@ -300,11 +304,15 @@ export class Discovery extends HTMLElement { cardHeader.appendChild(header) const cardBody = this.mkElement('div', '', { class: 'card-body' }) - const k = this.renderKernelOption(this.lastUsed, () => { - localStorage.removeItem(this.DISCOVERY_LAST_USED_KEY) - this.lastUsed = undefined - this.render() - }) + const k = this.renderKernelOption( + this.lastUsed, + () => { + localStorage.removeItem(this.DISCOVERY_LAST_USED_KEY) + this.lastUsed = undefined + this.render() + }, + true + ) cardBody.appendChild(k) card.append(cardHeader, cardBody) diff --git a/core/wallet-ui-components/src/windows/popup.ts b/core/wallet-ui-components/src/windows/popup.ts index 66618b412..96584f26a 100644 --- a/core/wallet-ui-components/src/windows/popup.ts +++ b/core/wallet-ui-components/src/windows/popup.ts @@ -33,13 +33,17 @@ class PopupInstance { } constructor() { - window.addEventListener('beforeunload', () => { + // Use multiple event listeners for better cross-browser compatibility + const closePopupOnUnload = () => { if (globalPopupInstance) { console.log('[PopupInstance] Closing popup instance on unload') globalPopupInstance.close() globalPopupInstance = undefined } - }) + } + + window.addEventListener('beforeunload', closePopupOnUnload) + window.addEventListener('unload', closePopupOnUnload) } open(url: string | URL): WindowProxy diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/lib/DA/Exception/ArithmeticError/module.d.ts b/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/lib/DA/Exception/ArithmeticError/module.d.ts index e862a7607..1f7206345 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/lib/DA/Exception/ArithmeticError/module.d.ts +++ b/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/lib/DA/Exception/ArithmeticError/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type ArithmeticError = { message: string diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/lib/DA/Exception/ArithmeticError/module.js b/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/lib/DA/Exception/ArithmeticError/module.js index 8144a1af5..903eb3e1a 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/lib/DA/Exception/ArithmeticError/module.js +++ b/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/lib/DA/Exception/ArithmeticError/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.ArithmeticError = { decoder: damlTypes.lazyMemo(function () { diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/package.json b/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/package.json index 36e2601b9..1025efec8 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/package.json +++ b/damljs/token-standard-models/daml-prim-DA-Exception-ArithmeticError-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-prim-DA-Exception-ArithmeticError-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/lib/DA/Exception/AssertionFailed/module.d.ts b/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/lib/DA/Exception/AssertionFailed/module.d.ts index acc44dbdd..144996aff 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/lib/DA/Exception/AssertionFailed/module.d.ts +++ b/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/lib/DA/Exception/AssertionFailed/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type AssertionFailed = { message: string diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/lib/DA/Exception/AssertionFailed/module.js b/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/lib/DA/Exception/AssertionFailed/module.js index 7f9d6e439..b950a99d5 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/lib/DA/Exception/AssertionFailed/module.js +++ b/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/lib/DA/Exception/AssertionFailed/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.AssertionFailed = { decoder: damlTypes.lazyMemo(function () { diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/package.json b/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/package.json index 34bc754ca..a37ead5dd 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/package.json +++ b/damljs/token-standard-models/daml-prim-DA-Exception-AssertionFailed-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-prim-DA-Exception-AssertionFailed-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/lib/DA/Exception/GeneralError/module.d.ts b/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/lib/DA/Exception/GeneralError/module.d.ts index 34c69b9ef..fc69c26db 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/lib/DA/Exception/GeneralError/module.d.ts +++ b/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/lib/DA/Exception/GeneralError/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type GeneralError = { message: string diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/lib/DA/Exception/GeneralError/module.js b/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/lib/DA/Exception/GeneralError/module.js index 49642fd9b..74b0158f5 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/lib/DA/Exception/GeneralError/module.js +++ b/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/lib/DA/Exception/GeneralError/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.GeneralError = { decoder: damlTypes.lazyMemo(function () { diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/package.json b/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/package.json index e8418ec28..6684a060e 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/package.json +++ b/damljs/token-standard-models/daml-prim-DA-Exception-GeneralError-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-prim-DA-Exception-GeneralError-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/lib/DA/Exception/PreconditionFailed/module.d.ts b/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/lib/DA/Exception/PreconditionFailed/module.d.ts index 5091c403d..d0eafdb58 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/lib/DA/Exception/PreconditionFailed/module.d.ts +++ b/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/lib/DA/Exception/PreconditionFailed/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type PreconditionFailed = { message: string diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/lib/DA/Exception/PreconditionFailed/module.js b/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/lib/DA/Exception/PreconditionFailed/module.js index 4a2dac778..fef75c48a 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/lib/DA/Exception/PreconditionFailed/module.js +++ b/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/lib/DA/Exception/PreconditionFailed/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.PreconditionFailed = { decoder: damlTypes.lazyMemo(function () { diff --git a/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/package.json b/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/package.json index 768cd36fc..949fc895b 100644 --- a/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/package.json +++ b/damljs/token-standard-models/daml-prim-DA-Exception-PreconditionFailed-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-prim-DA-Exception-PreconditionFailed-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/lib/DA/Types/module.d.ts b/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/lib/DA/Types/module.d.ts index 26aeb7d3d..75591e9c4 100644 --- a/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/lib/DA/Types/module.d.ts +++ b/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/lib/DA/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type Either = | { tag: 'Left'; value: a } diff --git a/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/lib/DA/Types/module.js b/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/lib/DA/Types/module.js index 3e4f49a61..3f76670a1 100644 --- a/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/lib/DA/Types/module.js +++ b/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/lib/DA/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.Either = function (a, b) { return { diff --git a/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/package.json b/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/package.json index b8e8462eb..dcec8aa04 100644 --- a/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-prim-DA-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-prim-DA-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/lib/GHC/Tuple/module.d.ts b/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/lib/GHC/Tuple/module.d.ts index aac520fcf..3c3121b04 100644 --- a/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/lib/GHC/Tuple/module.d.ts +++ b/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/lib/GHC/Tuple/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type Unit = { _1: a diff --git a/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/lib/GHC/Tuple/module.js b/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/lib/GHC/Tuple/module.js index 061e0cf28..0dbdf1afc 100644 --- a/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/lib/GHC/Tuple/module.js +++ b/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/lib/GHC/Tuple/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.Unit = function (a) { return { diff --git a/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/package.json b/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/package.json index 019fe1584..1e645ab3e 100644 --- a/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/package.json +++ b/damljs/token-standard-models/daml-prim-GHC-Tuple-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-prim-GHC-Tuple-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/lib/GHC/Types/module.d.ts b/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/lib/GHC/Types/module.d.ts index 73dcaa0b3..f985b6933 100644 --- a/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/lib/GHC/Types/module.d.ts +++ b/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/lib/GHC/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type Ordering = 'LT' | 'EQ' | 'GT' diff --git a/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/lib/GHC/Types/module.js b/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/lib/GHC/Types/module.js index f50ed42dc..75beded09 100644 --- a/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/lib/GHC/Types/module.js +++ b/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/lib/GHC/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.Ordering = { LT: 'LT', diff --git a/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/package.json b/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/package.json index bfa858db4..903bb3374 100644 --- a/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-prim-GHC-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-prim-GHC-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/lib/DA/Date/Types/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/lib/DA/Date/Types/module.d.ts index bbadae6f3..d68f38add 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/lib/DA/Date/Types/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/lib/DA/Date/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type DayOfWeek = | 'Monday' diff --git a/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/lib/DA/Date/Types/module.js b/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/lib/DA/Date/Types/module.js index 51826663b..4506a2bdd 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/lib/DA/Date/Types/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/lib/DA/Date/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.DayOfWeek = { Monday: 'Monday', diff --git a/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/package.json index 0032e842f..9c35864a3 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-Date-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-Date-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/lib/DA/Internal/Down/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/lib/DA/Internal/Down/module.d.ts index 81e3fda00..24945280f 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/lib/DA/Internal/Down/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/lib/DA/Internal/Down/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type Down = { unpack: a diff --git a/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/lib/DA/Internal/Down/module.js b/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/lib/DA/Internal/Down/module.js index 18698e685..1856a3610 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/lib/DA/Internal/Down/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/lib/DA/Internal/Down/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.Down = function (a) { return { diff --git a/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/package.json index ed9e05d8b..240c676d1 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-Internal-Down-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-Internal-Down-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/lib/DA/Logic/Types/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/lib/DA/Logic/Types/module.d.ts index 1b373e4fe..fa32b983c 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/lib/DA/Logic/Types/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/lib/DA/Logic/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type Formula = | { tag: 'Proposition'; value: a } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/lib/DA/Logic/Types/module.js b/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/lib/DA/Logic/Types/module.js index cd4cbb060..a30972297 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/lib/DA/Logic/Types/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/lib/DA/Logic/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.Formula = function (a) { return { diff --git a/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/package.json index fd35b2ce6..57185cd77 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-Logic-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-Logic-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/lib/DA/Monoid/Types/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/lib/DA/Monoid/Types/module.d.ts index 914a9a9ea..7b90c389b 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/lib/DA/Monoid/Types/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/lib/DA/Monoid/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type All = { getAll: boolean diff --git a/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/lib/DA/Monoid/Types/module.js b/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/lib/DA/Monoid/Types/module.js index f2677281d..f7b0f08bf 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/lib/DA/Monoid/Types/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/lib/DA/Monoid/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.All = { decoder: damlTypes.lazyMemo(function () { diff --git a/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/package.json index bdc37426b..0dc22fb2f 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-Monoid-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-Monoid-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/lib/DA/NonEmpty/Types/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/lib/DA/NonEmpty/Types/module.d.ts index 515545a29..8fce6cafc 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/lib/DA/NonEmpty/Types/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/lib/DA/NonEmpty/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type NonEmpty = { hd: a diff --git a/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/lib/DA/NonEmpty/Types/module.js b/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/lib/DA/NonEmpty/Types/module.js index 4dafc2405..0a4399130 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/lib/DA/NonEmpty/Types/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/lib/DA/NonEmpty/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.NonEmpty = function (a) { return { diff --git a/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/package.json index 08a0d416e..78b95ce93 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-NonEmpty-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-NonEmpty-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/lib/DA/Random/Types/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/lib/DA/Random/Types/module.d.ts index 695806be0..237253f20 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/lib/DA/Random/Types/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/lib/DA/Random/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type Minstd = { tag: 'Minstd'; value: damlTypes.Int } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/lib/DA/Random/Types/module.js b/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/lib/DA/Random/Types/module.js index c02b8f319..500b3d4f7 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/lib/DA/Random/Types/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/lib/DA/Random/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.Minstd = { decoder: damlTypes.lazyMemo(function () { diff --git a/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/package.json index 66c50dd33..a53d1f672 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-Random-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-Random-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/lib/DA/Semigroup/Types/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/lib/DA/Semigroup/Types/module.d.ts index 1398de885..b87a054d5 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/lib/DA/Semigroup/Types/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/lib/DA/Semigroup/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type Min = { unpack: a diff --git a/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/lib/DA/Semigroup/Types/module.js b/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/lib/DA/Semigroup/Types/module.js index 1b1e24559..5090637ee 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/lib/DA/Semigroup/Types/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/lib/DA/Semigroup/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.Min = function (a) { return { diff --git a/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/package.json index c32bfe051..972a4b47a 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-Semigroup-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-Semigroup-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/lib/DA/Set/Types/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/lib/DA/Set/Types/module.d.ts index 3047859ad..dc3730388 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/lib/DA/Set/Types/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/lib/DA/Set/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type Set = { map: damlTypes.Map diff --git a/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/lib/DA/Set/Types/module.js b/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/lib/DA/Set/Types/module.js index 4118237de..4f9c18c1b 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/lib/DA/Set/Types/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/lib/DA/Set/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.Set = function (k) { return { diff --git a/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/package.json index cd8fde7de..3ba6c4c58 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-Set-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-Set-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/lib/DA/Stack/Types/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/lib/DA/Stack/Types/module.d.ts index acfb38af8..ca24be566 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/lib/DA/Stack/Types/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/lib/DA/Stack/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type SrcLoc = { srcLocPackage: string diff --git a/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/lib/DA/Stack/Types/module.js b/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/lib/DA/Stack/Types/module.js index 3bc3fffdd..4b10f03e9 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/lib/DA/Stack/Types/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/lib/DA/Stack/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.SrcLoc = { decoder: damlTypes.lazyMemo(function () { diff --git a/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/package.json index 3180d366c..f5d2c5f59 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-Stack-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-Stack-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/lib/DA/Time/Types/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/lib/DA/Time/Types/module.d.ts index 9e6dc958a..cd7b804f4 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/lib/DA/Time/Types/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/lib/DA/Time/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type RelTime = { microseconds: damlTypes.Int diff --git a/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/lib/DA/Time/Types/module.js b/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/lib/DA/Time/Types/module.js index 5e5450716..099a484c7 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/lib/DA/Time/Types/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/lib/DA/Time/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.RelTime = { decoder: damlTypes.lazyMemo(function () { diff --git a/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/package.json index 534b5fe61..8c3d38bf1 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-Time-Types-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-Time-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/lib/DA/Validation/Types/module.d.ts b/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/lib/DA/Validation/Types/module.d.ts index ab39dc4b1..6b684664e 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/lib/DA/Validation/Types/module.d.ts +++ b/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/lib/DA/Validation/Types/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' import * as pkgbde4bd30749e99603e5afa354706608601029e225d4983324d617825b634253a from '@daml.js/daml-stdlib-DA-NonEmpty-Types-1.0.0' diff --git a/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/lib/DA/Validation/Types/module.js b/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/lib/DA/Validation/Types/module.js index 60748f9c6..fcef21d2e 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/lib/DA/Validation/Types/module.js +++ b/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/lib/DA/Validation/Types/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') var pkgbde4bd30749e99603e5afa354706608601029e225d4983324d617825b634253a = require('@daml.js/daml-stdlib-DA-NonEmpty-Types-1.0.0') diff --git a/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/package.json b/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/package.json index 92df6a71d..0b27afcd4 100644 --- a/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/package.json +++ b/damljs/token-standard-models/daml-stdlib-DA-Validation-Types-1.0.0/package.json @@ -3,15 +3,14 @@ "@daml.js/daml-stdlib-DA-NonEmpty-Types-1.0.0": "file:../daml-stdlib-DA-NonEmpty-Types-1.0.0", "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/daml-stdlib-DA-Validation-Types-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/daml.yaml b/damljs/token-standard-models/daml.yaml index aeecdfa2f..932ecf699 100644 --- a/damljs/token-standard-models/daml.yaml +++ b/damljs/token-standard-models/daml.yaml @@ -1,4 +1,4 @@ -sdk-version: 3.3.0-snapshot.20250603.0 +sdk-version: 3.4.9 build-options: - --enable-interfaces=yes name: token-standard-models diff --git a/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/lib/DA/Internal/Template/module.d.ts b/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/lib/DA/Internal/Template/module.d.ts index 0d3eac7ed..31100591a 100644 --- a/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/lib/DA/Internal/Template/module.d.ts +++ b/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/lib/DA/Internal/Template/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' export declare type Archive = {} diff --git a/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/lib/DA/Internal/Template/module.js b/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/lib/DA/Internal/Template/module.js index 832f1afd5..88a71f6f3 100644 --- a/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/lib/DA/Internal/Template/module.js +++ b/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/lib/DA/Internal/Template/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') exports.Archive = { decoder: damlTypes.lazyMemo(function () { diff --git a/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/package.json b/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/package.json index c65296fb7..bffc850e9 100644 --- a/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/package.json +++ b/damljs/token-standard-models/ghc-stdlib-DA-Internal-Template-1.0.0/package.json @@ -2,15 +2,14 @@ "dependencies": { "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationInstructionV1/module.d.ts b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationInstructionV1/module.d.ts index bab3a30fb..ede0da363 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationInstructionV1/module.d.ts +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationInstructionV1/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' import * as pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 from '@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0' @@ -14,7 +12,7 @@ import * as Splice_Api_Token_HoldingV1 from '../../../../Splice/Api/Token/Holdin import * as Splice_Api_Token_MetadataV1 from '../../../../Splice/Api/Token/MetadataV1/module' export declare type AllocationFactory = - damlTypes.Interface<'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationInstructionV1:AllocationFactory'> & + damlTypes.Interface<'#token-standard-models:Splice.Api.Token.AllocationInstructionV1:AllocationFactory'> & AllocationFactoryView export declare interface AllocationFactoryInterface { Archive: damlTypes.Choice< @@ -48,13 +46,13 @@ export declare interface AllocationFactoryInterface { export declare const AllocationFactory: damlTypes.InterfaceCompanion< AllocationFactory, undefined, - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationInstructionV1:AllocationFactory' + '#token-standard-models:Splice.Api.Token.AllocationInstructionV1:AllocationFactory' > & damlTypes.FromTemplate & AllocationFactoryInterface export declare type AllocationInstruction = - damlTypes.Interface<'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationInstructionV1:AllocationInstruction'> & + damlTypes.Interface<'#token-standard-models:Splice.Api.Token.AllocationInstructionV1:AllocationInstruction'> & AllocationInstructionView export declare interface AllocationInstructionInterface { Archive: damlTypes.Choice< @@ -88,7 +86,7 @@ export declare interface AllocationInstructionInterface { export declare const AllocationInstruction: damlTypes.InterfaceCompanion< AllocationInstruction, undefined, - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationInstructionV1:AllocationInstruction' + '#token-standard-models:Splice.Api.Token.AllocationInstructionV1:AllocationInstruction' > & damlTypes.FromTemplate & AllocationInstructionInterface diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationInstructionV1/module.js b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationInstructionV1/module.js index 9551c561a..ef0dec3b1 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationInstructionV1/module.js +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationInstructionV1/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') var pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 = require('@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0') @@ -19,7 +17,8 @@ var Splice_Api_Token_HoldingV1 = require('../../../../Splice/Api/Token/HoldingV1 var Splice_Api_Token_MetadataV1 = require('../../../../Splice/Api/Token/MetadataV1/module') exports.AllocationFactory = damlTypes.assembleInterface( - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationInstructionV1:AllocationFactory', + '#token-standard-models:Splice.Api.Token.AllocationInstructionV1:AllocationFactory', + '3c373f302ebb5531459ceca3b6f0409365d119767ffe2026a04e6bd750dae10d:Splice.Api.Token.AllocationInstructionV1:AllocationFactory', function () { return exports.AllocationFactoryView }, @@ -85,7 +84,8 @@ exports.AllocationFactory = damlTypes.assembleInterface( ) exports.AllocationInstruction = damlTypes.assembleInterface( - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationInstructionV1:AllocationInstruction', + '#token-standard-models:Splice.Api.Token.AllocationInstructionV1:AllocationInstruction', + '3c373f302ebb5531459ceca3b6f0409365d119767ffe2026a04e6bd750dae10d:Splice.Api.Token.AllocationInstructionV1:AllocationInstruction', function () { return exports.AllocationInstructionView }, diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationRequestV1/module.d.ts b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationRequestV1/module.d.ts index c8da49e08..45d5ce3d3 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationRequestV1/module.d.ts +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationRequestV1/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' import * as pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 from '@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0' @@ -13,7 +11,7 @@ import * as Splice_Api_Token_AllocationV1 from '../../../../Splice/Api/Token/All import * as Splice_Api_Token_MetadataV1 from '../../../../Splice/Api/Token/MetadataV1/module' export declare type AllocationRequest = - damlTypes.Interface<'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationRequestV1:AllocationRequest'> & + damlTypes.Interface<'#token-standard-models:Splice.Api.Token.AllocationRequestV1:AllocationRequest'> & AllocationRequestView export declare interface AllocationRequestInterface { Archive: damlTypes.Choice< @@ -47,7 +45,7 @@ export declare interface AllocationRequestInterface { export declare const AllocationRequest: damlTypes.InterfaceCompanion< AllocationRequest, undefined, - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationRequestV1:AllocationRequest' + '#token-standard-models:Splice.Api.Token.AllocationRequestV1:AllocationRequest' > & damlTypes.FromTemplate & AllocationRequestInterface diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationRequestV1/module.js b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationRequestV1/module.js index 07dde3986..1720cae02 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationRequestV1/module.js +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationRequestV1/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') var pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 = require('@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0') @@ -18,7 +16,8 @@ var Splice_Api_Token_AllocationV1 = require('../../../../Splice/Api/Token/Alloca var Splice_Api_Token_MetadataV1 = require('../../../../Splice/Api/Token/MetadataV1/module') exports.AllocationRequest = damlTypes.assembleInterface( - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationRequestV1:AllocationRequest', + '#token-standard-models:Splice.Api.Token.AllocationRequestV1:AllocationRequest', + '3c373f302ebb5531459ceca3b6f0409365d119767ffe2026a04e6bd750dae10d:Splice.Api.Token.AllocationRequestV1:AllocationRequest', function () { return exports.AllocationRequestView }, diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationV1/module.d.ts b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationV1/module.d.ts index 4c23cd744..e1124e719 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationV1/module.d.ts +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationV1/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' import * as pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 from '@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0' @@ -13,7 +11,7 @@ import * as Splice_Api_Token_HoldingV1 from '../../../../Splice/Api/Token/Holdin import * as Splice_Api_Token_MetadataV1 from '../../../../Splice/Api/Token/MetadataV1/module' export declare type Allocation = - damlTypes.Interface<'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationV1:Allocation'> & + damlTypes.Interface<'#token-standard-models:Splice.Api.Token.AllocationV1:Allocation'> & AllocationView export declare interface AllocationInterface { Archive: damlTypes.Choice< @@ -56,7 +54,7 @@ export declare interface AllocationInterface { export declare const Allocation: damlTypes.InterfaceCompanion< Allocation, undefined, - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationV1:Allocation' + '#token-standard-models:Splice.Api.Token.AllocationV1:Allocation' > & damlTypes.FromTemplate & AllocationInterface diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationV1/module.js b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationV1/module.js index 338556210..cf075b319 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationV1/module.js +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/AllocationV1/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') var pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 = require('@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0') @@ -18,7 +16,8 @@ var Splice_Api_Token_HoldingV1 = require('../../../../Splice/Api/Token/HoldingV1 var Splice_Api_Token_MetadataV1 = require('../../../../Splice/Api/Token/MetadataV1/module') exports.Allocation = damlTypes.assembleInterface( - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.AllocationV1:Allocation', + '#token-standard-models:Splice.Api.Token.AllocationV1:Allocation', + '3c373f302ebb5531459ceca3b6f0409365d119767ffe2026a04e6bd750dae10d:Splice.Api.Token.AllocationV1:Allocation', function () { return exports.AllocationView }, diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/HoldingV1/module.d.ts b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/HoldingV1/module.d.ts index 075e8b1a4..02a093a47 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/HoldingV1/module.d.ts +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/HoldingV1/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' import * as pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 from '@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0' import * as pkgb70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946 from '@daml.js/daml-stdlib-DA-Time-Types-1.0.0' @@ -13,7 +11,7 @@ import * as pkgb70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946 import * as Splice_Api_Token_MetadataV1 from '../../../../Splice/Api/Token/MetadataV1/module' export declare type Holding = - damlTypes.Interface<'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.HoldingV1:Holding'> & + damlTypes.Interface<'#token-standard-models:Splice.Api.Token.HoldingV1:Holding'> & HoldingView export declare interface HoldingInterface { Archive: damlTypes.Choice< @@ -27,7 +25,7 @@ export declare interface HoldingInterface { export declare const Holding: damlTypes.InterfaceCompanion< Holding, undefined, - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.HoldingV1:Holding' + '#token-standard-models:Splice.Api.Token.HoldingV1:Holding' > & damlTypes.FromTemplate & HoldingInterface diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/HoldingV1/module.js b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/HoldingV1/module.js index f4ec48a58..ee3a778e9 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/HoldingV1/module.js +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/HoldingV1/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') var pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 = require('@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0') var pkgb70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946 = require('@daml.js/daml-stdlib-DA-Time-Types-1.0.0') @@ -18,7 +16,8 @@ var pkgb70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946 = requir var Splice_Api_Token_MetadataV1 = require('../../../../Splice/Api/Token/MetadataV1/module') exports.Holding = damlTypes.assembleInterface( - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.HoldingV1:Holding', + '#token-standard-models:Splice.Api.Token.HoldingV1:Holding', + '3c373f302ebb5531459ceca3b6f0409365d119767ffe2026a04e6bd750dae10d:Splice.Api.Token.HoldingV1:Holding', function () { return exports.HoldingView }, diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/MetadataV1/module.d.ts b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/MetadataV1/module.d.ts index 3423223e0..eabf10bd7 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/MetadataV1/module.d.ts +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/MetadataV1/module.d.ts @@ -4,14 +4,12 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' import * as pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 from '@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0' import * as pkgb70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946 from '@daml.js/daml-stdlib-DA-Time-Types-1.0.0' export declare type AnyContract = - damlTypes.Interface<'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.MetadataV1:AnyContract'> & + damlTypes.Interface<'#token-standard-models:Splice.Api.Token.MetadataV1:AnyContract'> & AnyContractView export declare interface AnyContractInterface { Archive: damlTypes.Choice< @@ -27,7 +25,7 @@ export declare interface AnyContractInterface { export declare const AnyContract: damlTypes.InterfaceCompanion< AnyContract, undefined, - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.MetadataV1:AnyContract' + '#token-standard-models:Splice.Api.Token.MetadataV1:AnyContract' > & damlTypes.FromTemplate & AnyContractInterface diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/MetadataV1/module.js b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/MetadataV1/module.js index a6f8ff919..e02903848 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/MetadataV1/module.js +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/MetadataV1/module.js @@ -9,14 +9,13 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') var pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 = require('@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0') var pkgb70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946 = require('@daml.js/daml-stdlib-DA-Time-Types-1.0.0') exports.AnyContract = damlTypes.assembleInterface( - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.MetadataV1:AnyContract', + '#token-standard-models:Splice.Api.Token.MetadataV1:AnyContract', + '3c373f302ebb5531459ceca3b6f0409365d119767ffe2026a04e6bd750dae10d:Splice.Api.Token.MetadataV1:AnyContract', function () { return exports.AnyContractView }, diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/TransferInstructionV1/module.d.ts b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/TransferInstructionV1/module.d.ts index 77ea266e3..eceeb3c43 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/TransferInstructionV1/module.d.ts +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/TransferInstructionV1/module.d.ts @@ -4,8 +4,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import * as jtv from '@mojotech/json-type-validation' import * as damlTypes from '@daml/types' -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ -import * as damlLedger from '@daml/ledger' import * as pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 from '@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0' @@ -13,7 +11,7 @@ import * as Splice_Api_Token_HoldingV1 from '../../../../Splice/Api/Token/Holdin import * as Splice_Api_Token_MetadataV1 from '../../../../Splice/Api/Token/MetadataV1/module' export declare type TransferFactory = - damlTypes.Interface<'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.TransferInstructionV1:TransferFactory'> & + damlTypes.Interface<'#token-standard-models:Splice.Api.Token.TransferInstructionV1:TransferFactory'> & TransferFactoryView export declare interface TransferFactoryInterface { Archive: damlTypes.Choice< @@ -47,13 +45,13 @@ export declare interface TransferFactoryInterface { export declare const TransferFactory: damlTypes.InterfaceCompanion< TransferFactory, undefined, - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.TransferInstructionV1:TransferFactory' + '#token-standard-models:Splice.Api.Token.TransferInstructionV1:TransferFactory' > & damlTypes.FromTemplate & TransferFactoryInterface export declare type TransferInstruction = - damlTypes.Interface<'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.TransferInstructionV1:TransferInstruction'> & + damlTypes.Interface<'#token-standard-models:Splice.Api.Token.TransferInstructionV1:TransferInstruction'> & TransferInstructionView export declare interface TransferInstructionInterface { Archive: damlTypes.Choice< @@ -105,7 +103,7 @@ export declare interface TransferInstructionInterface { export declare const TransferInstruction: damlTypes.InterfaceCompanion< TransferInstruction, undefined, - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.TransferInstructionV1:TransferInstruction' + '#token-standard-models:Splice.Api.Token.TransferInstructionV1:TransferInstruction' > & damlTypes.FromTemplate & TransferInstructionInterface diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/TransferInstructionV1/module.js b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/TransferInstructionV1/module.js index 3bfde823e..bef743ec0 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/TransferInstructionV1/module.js +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/Splice/Api/Token/TransferInstructionV1/module.js @@ -9,8 +9,6 @@ Object.defineProperty(exports, '__esModule', { value: true }) var jtv = require('@mojotech/json-type-validation') /* eslint-disable-next-line no-unused-vars */ var damlTypes = require('@daml/types') -/* eslint-disable-next-line no-unused-vars */ -var damlLedger = require('@daml/ledger') var pkg9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69 = require('@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0') @@ -18,7 +16,8 @@ var Splice_Api_Token_HoldingV1 = require('../../../../Splice/Api/Token/HoldingV1 var Splice_Api_Token_MetadataV1 = require('../../../../Splice/Api/Token/MetadataV1/module') exports.TransferFactory = damlTypes.assembleInterface( - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.TransferInstructionV1:TransferFactory', + '#token-standard-models:Splice.Api.Token.TransferInstructionV1:TransferFactory', + '3c373f302ebb5531459ceca3b6f0409365d119767ffe2026a04e6bd750dae10d:Splice.Api.Token.TransferInstructionV1:TransferFactory', function () { return exports.TransferFactoryView }, @@ -84,7 +83,8 @@ exports.TransferFactory = damlTypes.assembleInterface( ) exports.TransferInstruction = damlTypes.assembleInterface( - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c:Splice.Api.Token.TransferInstructionV1:TransferInstruction', + '#token-standard-models:Splice.Api.Token.TransferInstructionV1:TransferInstruction', + '3c373f302ebb5531459ceca3b6f0409365d119767ffe2026a04e6bd750dae10d:Splice.Api.Token.TransferInstructionV1:TransferInstruction', function () { return exports.TransferInstructionView }, diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/index.d.ts b/damljs/token-standard-models/token-standard-models-1.0.0/lib/index.d.ts index 7ff167028..724f4de88 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/index.d.ts +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/index.d.ts @@ -1,4 +1,4 @@ import * as Splice from './Splice' export { Splice } export declare const packageId = - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c' + '3c373f302ebb5531459ceca3b6f0409365d119767ffe2026a04e6bd750dae10d' diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/lib/index.js b/damljs/token-standard-models/token-standard-models-1.0.0/lib/index.js index e35bcc35d..a003c2ae4 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/lib/index.js +++ b/damljs/token-standard-models/token-standard-models-1.0.0/lib/index.js @@ -8,4 +8,4 @@ Object.defineProperty(exports, '__esModule', { value: true }) var Splice = require('./Splice') exports.Splice = Splice exports.packageId = - 'a132be8b23c8515da6c828dd97519a73d9c8b1aa6f9cddd3c7acc206e4b41f8c' + '3c373f302ebb5531459ceca3b6f0409365d119767ffe2026a04e6bd750dae10d' diff --git a/damljs/token-standard-models/token-standard-models-1.0.0/package.json b/damljs/token-standard-models/token-standard-models-1.0.0/package.json index e7f8ff235..e00972353 100644 --- a/damljs/token-standard-models/token-standard-models-1.0.0/package.json +++ b/damljs/token-standard-models/token-standard-models-1.0.0/package.json @@ -4,15 +4,14 @@ "@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0": "file:../ghc-stdlib-DA-Internal-Template-1.0.0", "@mojotech/json-type-validation": "^3.1.0" }, - "description": "Generated by `daml codegen js` from SDK 3.3.0-snapshot.20250603.0", + "description": "Generated by `daml codegen js` from SDK 0.0.0", "license": "UNLICENSED", "main": "lib/index.js", "name": "@daml.js/token-standard-models-1.0.0", "peer-dependencies": { - "@daml/ledger": "3.3.0-snapshot.20250528.13806.0.v3cd439fb", - "@daml/types": "3.3.0-snapshot.20250528.13806.0.v3cd439fb" + "@daml/types": "0.0.0" }, "private": true, "types": "lib/index.d.ts", - "version": "3.3.0-snapshot.20250603.0" + "version": "0.0.0" } diff --git a/docs/wallet-integration-guide/examples/package.json b/docs/wallet-integration-guide/examples/package.json index 92312f645..53d70baed 100644 --- a/docs/wallet-integration-guide/examples/package.json +++ b/docs/wallet-integration-guide/examples/package.json @@ -30,6 +30,7 @@ "run-17": "tsx ./scripts/17-input-cid-filtering.ts | pino-pretty", "run-18": "tsx ./scripts/18-merge-delegation-proposal.ts | pino-pretty", "run-19": "tsx ./scripts/19-create-party-with-preapproval.ts | pino-pretty", + "run-20": "tsx ./scripts/20-active-contracts-loop.ts | pino-pretty", "run-exch-01": "tsx ./scripts/exchange-integration/01-one-step-deposit.ts | pino-pretty", "run-exch-02": "tsx ./scripts/exchange-integration/02-one-step-withdrawal.ts | pino-pretty", "run-exch-03": "tsx ./scripts/exchange-integration/03-multi-step-deposit.ts | pino-pretty", diff --git a/docs/wallet-integration-guide/examples/scripts/07-token-standard-reject-expire-withdraw-localnet.ts b/docs/wallet-integration-guide/examples/scripts/07-token-standard-reject-expire-withdraw-localnet.ts index 52fa4fcd9..af5776a8b 100644 --- a/docs/wallet-integration-guide/examples/scripts/07-token-standard-reject-expire-withdraw-localnet.ts +++ b/docs/wallet-integration-guide/examples/scripts/07-token-standard-reject-expire-withdraw-localnet.ts @@ -1,3 +1,4 @@ +import { Holding, PrettyContract } from '@canton-network/core-ledger-client' import { WalletSDKImpl, localNetAuthDefault, @@ -15,6 +16,9 @@ const logger = pino({ level: 'info', }) +const originalTap = 200000 +const transferAmount = 100 + // it is important to configure the SDK correctly else you might run into connectivity or authentication issues const sdk = new WalletSDKImpl().configure({ logger, @@ -24,43 +28,44 @@ const sdk = new WalletSDKImpl().configure({ tokenStandardFactory: localNetTokenStandardDefault, }) -type UtxoLockedCounts = { - locked: 0 - unlocked: 0 +type AllHoldings = { + locked: PrettyContract[] + unlocked: PrettyContract[] } -const getHoldingUtxosCountGroupedByLock = - async (): Promise => { - const utxosUnlocked = await sdk.tokenStandard?.listHoldingUtxos(false) - const utxosAll = await sdk.tokenStandard?.listHoldingUtxos(true) - const utxosUnlockedCids = utxosUnlocked!.map((utxo) => utxo.contractId) - - return utxosAll!.reduce( - (accumulator, utxo) => { - const isUnlocked = utxosUnlockedCids.includes(utxo.contractId) - if (isUnlocked) { - accumulator.unlocked++ - } else { - accumulator.locked++ - } - return accumulator - }, - { - locked: 0, - unlocked: 0, - } - ) +const getHoldingUtxosCountGroupedByLock = async (): Promise => { + const utxosUnlocked = await sdk.tokenStandard?.listHoldingUtxos(false) + const utxosAll = await sdk.tokenStandard?.listHoldingUtxos(true) + + return { + locked: + utxosAll?.filter( + (utxo) => + !utxosUnlocked?.some( + (unlocked) => unlocked.contractId === utxo.contractId + ) + ) || [], + unlocked: utxosUnlocked || [], } +} const assertLockedAmount = ( - utxoLockedCounts: UtxoLockedCounts, - expectedLocked: number, - expectedUnlocked: number | null + utxoLockedCounts: AllHoldings, + expectedLockedAmount: number, + expectedUnlockedAmount: number ): void => { + const lockedSum = utxoLockedCounts.locked.reduce( + (sum, holding) => sum + Number(holding.interfaceViewValue.amount), + 0 + ) + const unlockedSum = utxoLockedCounts.unlocked.reduce( + (sum, holding) => sum + Number(holding.interfaceViewValue.amount), + 0 + ) + if ( - utxoLockedCounts.locked === expectedLocked && - (expectedUnlocked === null || - utxoLockedCounts.unlocked === expectedUnlocked) + lockedSum === expectedLockedAmount && + unlockedSum === expectedUnlockedAmount ) { return } @@ -68,12 +73,14 @@ const assertLockedAmount = ( logger.error( { utxoLockedCounts, - expectedLocked, - expectedUnlocked, + lockedSum: lockedSum.toString(), + unlockedSum: unlockedSum.toString(), + expectedLockedAmount, + expectedUnlockedAmount, }, - 'Unexpected count of locked/unlocked Holding UTXOs' + 'Unexpected sum of locked/unlocked Holding amounts' ) - throw new Error('Unexpected count of locked/unlocked Holding UTXOs') + throw new Error('Unexpected sum of locked/unlocked Holding amounts') } logger.info('SDK initialized') @@ -103,15 +110,6 @@ const receiver = await sdk.userLedger?.signAndAllocateExternalParty( ) logger.info(`Created party: ${receiver!.partyId}`) -await sdk.userLedger - ?.listWallets() - .then((wallets) => { - logger.info(wallets, 'Wallets:') - }) - .catch((error) => { - logger.error({ error }, 'Error listing wallets') - }) - sdk.tokenStandard?.setTransferFactoryRegistryUrl( localNetStaticConfig.LOCALNET_REGISTRY_API_URL ) @@ -121,7 +119,7 @@ const instrumentAdminPartyId = // mint holdings for Alice const [tapCommand, disclosedContracts] = await sdk.tokenStandard!.createTap( sender!.partyId, - '2000000', + originalTap.toString(), { instrumentId: 'Amulet', instrumentAdmin: instrumentAdminPartyId, @@ -141,7 +139,7 @@ const [transferCommandToReject, disclosedContracts2] = await sdk.tokenStandard!.createTransfer( sender!.partyId, receiver!.partyId, - '100', + transferAmount.toString(), { instrumentId: 'Amulet', instrumentAdmin: instrumentAdminPartyId, @@ -160,7 +158,11 @@ logger.info('Submitted transfer transaction (reject)') const senderUtxosBeforeRejected = await getHoldingUtxosCountGroupedByLock() logger.info({ senderUtxosBeforeRejected }) -assertLockedAmount(senderUtxosBeforeRejected, 1, null) +assertLockedAmount( + senderUtxosBeforeRejected, + transferAmount, + originalTap - transferAmount +) // Bob rejects the transfer await sdk.setPartyId(receiver!.partyId) @@ -188,11 +190,7 @@ logger.info('Rejected transfer instruction') await sdk.setPartyId(sender!.partyId) const senderUtxosAfterRejected = await getHoldingUtxosCountGroupedByLock() logger.info({ senderUtxosAfterRejected }) -assertLockedAmount( - senderUtxosAfterRejected, - 0, - senderUtxosBeforeRejected.unlocked + 1 -) +assertLockedAmount(senderUtxosAfterRejected, 0, originalTap) const EXPIRATION_MS = 10_000 const expiryDate = new Date(Date.now() + EXPIRATION_MS) @@ -202,7 +200,7 @@ const [transferCommandToExpire, disclosedContracts4] = await sdk.tokenStandard!.createTransfer( sender!.partyId, receiver!.partyId, - '100', + transferAmount.toString(), { instrumentId: 'Amulet', instrumentAdmin: instrumentAdminPartyId, @@ -222,7 +220,11 @@ logger.info('Submitted transfer transaction (expire)') const senderUtxosBeforeExpired = await getHoldingUtxosCountGroupedByLock() logger.info({ senderUtxosBeforeExpired }) -assertLockedAmount(senderUtxosBeforeExpired, 1, null) +assertLockedAmount( + senderUtxosBeforeExpired, + transferAmount, + originalTap - transferAmount +) const pendingInstructions2 = await sdk.tokenStandard?.fetchPendingTransferInstructionView() @@ -234,11 +236,7 @@ await new Promise((res) => setTimeout(res, EXPIRATION_MS + 5_000)) const senderUtxosAfterExpired = await getHoldingUtxosCountGroupedByLock() logger.info({ senderUtxosAfterExpired }) -assertLockedAmount( - senderUtxosAfterExpired, - 0, - senderUtxosBeforeExpired.unlocked + 1 -) +assertLockedAmount(senderUtxosAfterExpired, 0, originalTap) // Alice creates transfer that will be withdrawn logger.info('Creating transfer transaction (withdraw)') @@ -246,7 +244,7 @@ const [transferCommandToWithdraw, disclosedContracts5] = await sdk.tokenStandard!.createTransfer( sender!.partyId, receiver!.partyId, - '100', + transferAmount.toString(), { instrumentId: 'Amulet', instrumentAdmin: instrumentAdminPartyId, @@ -265,7 +263,11 @@ logger.info('Submitted transfer transaction (withdraw)') const senderUtxosBeforeWithdraw = await getHoldingUtxosCountGroupedByLock() logger.info({ senderUtxosBeforeWithdraw }) -assertLockedAmount(senderUtxosBeforeWithdraw, 1, null) +assertLockedAmount( + senderUtxosBeforeWithdraw, + transferAmount, + originalTap - transferAmount +) const pendingInstructions3 = await sdk.tokenStandard?.fetchPendingTransferInstructionView() @@ -295,18 +297,14 @@ logger.info('Withdrawn transfer instruction') const senderUtxosAfterWithdraw = await getHoldingUtxosCountGroupedByLock() logger.info({ senderUtxosAfterWithdraw }) -assertLockedAmount( - senderUtxosAfterWithdraw, - 0, - senderUtxosBeforeWithdraw.unlocked + 1 -) +assertLockedAmount(senderUtxosAfterWithdraw, 0, originalTap) // Alice creates transfer to Bob to accept using reclaimed holdings const [transferCommandToAccept, disclosedContracts7] = await sdk.tokenStandard!.createTransfer( sender!.partyId, receiver!.partyId, - '100', + transferAmount.toString(), { instrumentId: 'Amulet', instrumentAdmin: instrumentAdminPartyId, diff --git a/docs/wallet-integration-guide/examples/scripts/20-active-contracts-loop.ts b/docs/wallet-integration-guide/examples/scripts/20-active-contracts-loop.ts new file mode 100644 index 000000000..fa255a48e --- /dev/null +++ b/docs/wallet-integration-guide/examples/scripts/20-active-contracts-loop.ts @@ -0,0 +1,192 @@ +import { GenerateTransactionResponse } from '@canton-network/core-ledger-client' +import { PrivateKey } from '@canton-network/core-ledger-proto' +import { PartyId } from '@canton-network/core-types' +import { + WalletSDKImpl, + localNetAuthDefault, + localNetLedgerDefault, + localNetTokenStandardDefault, + createKeyPair, + localNetStaticConfig, +} from '@canton-network/wallet-sdk' +import { pino } from 'pino' +import { v4 } from 'uuid' + +const logger = pino({ name: '20-pagination', level: 'info' }) + +const sdk = new WalletSDKImpl().configure({ + logger, + authFactory: localNetAuthDefault, + ledgerFactory: localNetLedgerDefault, + tokenStandardFactory: localNetTokenStandardDefault, +}) + +logger.info('SDK initialized') + +await sdk.connect() +logger.info('Connected to ledger') + +const keyPairSender = createKeyPair() +const keyPairReceiver = createKeyPair() + +await sdk.connectTopology(localNetStaticConfig.LOCALNET_SCAN_PROXY_API_URL) + +const sender = await sdk.userLedger?.signAndAllocateExternalParty( + keyPairSender.privateKey, + 'alice' +) +logger.info(`Created party: ${sender!.partyId}`) +await sdk.setPartyId(sender!.partyId) + +const receiver = await sdk.userLedger?.signAndAllocateExternalParty( + keyPairReceiver.privateKey, + 'bob' +) +logger.info(`Created party: ${receiver!.partyId}`) + +sdk.tokenStandard?.setTransferFactoryRegistryUrl( + localNetStaticConfig.LOCALNET_REGISTRY_API_URL +) + +await sdk.setPartyId(receiver?.partyId!) +const validatorOperatorParty = await sdk.validator?.getValidatorUser() + +const instrumentAdminPartyId = + (await sdk.tokenStandard?.getInstrumentAdmin()) || '' + +logger.info('creating transfer preapproval proposal') + +await sdk.setPartyId(validatorOperatorParty!) +await sdk.tokenStandard?.createAndSubmitTapInternal( + validatorOperatorParty!, + '20000000', + { + instrumentId: 'Amulet', + instrumentAdmin: instrumentAdminPartyId, + } +) + +logger.info('transfer pre approval proposal is created') + +const createTapOperation = async (partyId: PartyId, privateKey: string) => { + let retries = 0 + const maxRetries = 10 + let success = false + + while (!success && retries < maxRetries) { + try { + const [tapCommand, disclosedContracts] = + await sdk.tokenStandard!.createTap(partyId, '1', { + instrumentId: 'Amulet', + instrumentAdmin: instrumentAdminPartyId, + }) + + await sdk.userLedger?.prepareSignExecuteAndWaitFor( + tapCommand, + privateKey, + v4(), + disclosedContracts + ) + success = true + } catch (error: any) { + if ( + error.message?.includes( + 'OpenMiningRound active at current moment not found' + ) + ) { + retries++ + logger.info( + `No active mining round, waiting 2 seconds... (retry ${retries}/${maxRetries})` + ) + await new Promise((resolve) => setTimeout(resolve, 2000)) + } else { + throw error + } + } + } + + if (!success) { + throw new Error( + `Failed to create TAP after ${maxRetries} retries. No active mining round available.` + ) + } +} + +await sdk.setPartyId(sender?.partyId!) + +// create more than node limit (200 by default) contracts for pagination test +const ALICE_UTXOS_AMOUNT = 250 +const BOB_UTXOS_AMOUNT = 4 +const batchSize = 20 +for ( + let batchStart = 0; + batchStart < ALICE_UTXOS_AMOUNT; + batchStart += batchSize +) { + const batchPromises = Array.from( + { length: Math.min(batchSize, ALICE_UTXOS_AMOUNT - batchStart) }, + (_, idx) => { + return (async () => { + await createTapOperation( + sender!.partyId, + keyPairSender.privateKey + ) + const shouldCreateOtherPartyTap = + [1, 2, 5].includes(idx) && batchStart === 0 + // test if we loop over another party's contracts + if (shouldCreateOtherPartyTap) { + await sdk.setPartyId(receiver?.partyId!) + await createTapOperation( + receiver!.partyId, + keyPairReceiver.privateKey + ) + await sdk.setPartyId(sender?.partyId!) + } + })() + } + ) + + await Promise.all(batchPromises) + logger.info( + `Created ${Math.min(batchStart + batchSize, ALICE_UTXOS_AMOUNT)} TAP loops` + ) +} + +await sdk.setPartyId(receiver?.partyId!) +await createTapOperation(receiver!.partyId, keyPairReceiver.privateKey) + +const testExistingUtxos = async ( + partyId: PartyId, + expectedUtxosAmount: number +) => { + await sdk.setPartyId(partyId) + const utxos = await sdk.tokenStandard?.listHoldingUtxos( + false, + 200, + undefined, + undefined, + true + ) // 200 is the http-list-max-elements-limit default + logger.info(`number of unlocked utxos for ${partyId} ${utxos?.length}`) + + const sumAmountFromUtxos = utxos?.reduce( + (acc, value) => acc + +value.interfaceViewValue.amount, + 0 + ) + + logger.info({ + expectedUtxosAmount, + sumAmountFromUtxos, + }) + + if (sumAmountFromUtxos !== expectedUtxosAmount) { + throw new Error( + `sumAmountFromUtxos (${sumAmountFromUtxos}) should be equal to totalAmount (${expectedUtxosAmount})` + ) + } + + logger.info({ partyId }, 'TEST SUCCESSFUL for') +} + +await testExistingUtxos(sender!.partyId, ALICE_UTXOS_AMOUNT) +await testExistingUtxos(receiver!.partyId, BOB_UTXOS_AMOUNT) diff --git a/eslint.config.mjs b/eslint.config.mjs index 5dcfda0a5..62c24c04a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -31,6 +31,7 @@ export default defineConfig([ 'core/wallet-dapp-remote-rpc-client', 'core/wallet-user-rpc-client', 'core/ledger-client/src/generated-clients', + 'core/ledger-client-types/src/generated-clients', 'damljs/**', 'docs/wallet-integration-guide/examples/**', 'examples/ping/playwright-report/**', diff --git a/examples/ping/package.json b/examples/ping/package.json index bda422ccd..9d76d8d62 100644 --- a/examples/ping/package.json +++ b/examples/ping/package.json @@ -7,6 +7,7 @@ "dev": "vite", "build": "tsc -b && vite build", "e2e": "nx playwright:e2e --ui", + "e2e2": "nx playwright:e2e", "preview": "vite preview" }, "dependencies": { diff --git a/examples/ping/src/App.tsx b/examples/ping/src/App.tsx index 2081513ef..a44226c10 100644 --- a/examples/ping/src/App.tsx +++ b/examples/ping/src/App.tsx @@ -10,21 +10,23 @@ import { LedgerSubmission } from './components/LedgerSubmission' import { Accounts } from './components/Accounts' import { PostEvents } from './components/PostEvents' import { WindowMessages } from './components/WindowMessages' +import { useStatus } from './hooks/useStatus' function App() { const { errorMsg, setErrorMsg } = useContext(ErrorContext) const [loading, setLoading] = useState(false) const [activeTab, setActiveTab] = useState('accounts') - const { connect, disconnect, status } = useConnect() + const { connect, disconnect, connectResult } = useConnect() + const { status, statusEvent } = useStatus() - const accounts = useAccounts(status) + const accounts = useAccounts(connectResult) const primaryParty = accounts?.find((w) => w.primary)?.partyId const [ledgerApiVersion, setLedgerApiVersion] = useState() useEffect(() => { - if (status?.isNetworkConnected) { + if (connectResult?.isNetworkConnected) { sdk.ledgerApi({ requestMethod: 'GET', resource: '/v2/version', @@ -33,7 +35,7 @@ function App() { setLedgerApiVersion(version) }) } - }, [status]) + }, [connectResult]) return (
@@ -46,7 +48,7 @@ function App() { justifyContent: 'center', }} > - {status?.isConnected ? ( + {connectResult?.isConnected ? ( )}
- {status?.isConnected && ( + {connectResult?.isConnected && ( - {status?.isConnected && ( + {connectResult?.isConnected && (
- +
@@ -197,7 +203,7 @@ function App() { }} > diff --git a/examples/ping/src/components/Accounts.tsx b/examples/ping/src/components/Accounts.tsx index c1e6ea3e7..d6cdd211c 100644 --- a/examples/ping/src/components/Accounts.tsx +++ b/examples/ping/src/components/Accounts.tsx @@ -1,10 +1,10 @@ import * as sdk from '@canton-network/dapp-sdk' import { useAccounts } from '../hooks/useAccounts' -export function Accounts(props: { status?: sdk.dappAPI.StatusEvent }) { - const accounts = useAccounts(props.status) +export function Accounts(props: { connectResult?: sdk.dappAPI.ConnectResult }) { + const accounts = useAccounts(props.connectResult) - const connected = props.status?.isConnected ?? false + const connected = props.connectResult?.isConnected ?? false const getAccountColor = (account: sdk.dappAPI.Wallet) => { if (account.disabled) { diff --git a/examples/ping/src/components/LedgerQuery.tsx b/examples/ping/src/components/LedgerQuery.tsx index a9a8f738f..010e4da5a 100644 --- a/examples/ping/src/components/LedgerQuery.tsx +++ b/examples/ping/src/components/LedgerQuery.tsx @@ -6,14 +6,14 @@ import { prettyjson } from '../utils' export function LedgerQuery(props: { primaryParty?: string ledgerApiVersion?: string - status?: sdk.dappAPI.StatusEvent + connectResult?: sdk.dappAPI.ConnectResult }) { const [loading, setLoading] = useState(false) const [queryResponses, setQueryResponses] = useState< Array<{ timestamp: Date; data: object }> >([]) - const connected = props.status?.isConnected ?? false + const connected = props.connectResult?.isConnected ?? false return ( connected && ( diff --git a/examples/ping/src/components/LedgerSubmission.tsx b/examples/ping/src/components/LedgerSubmission.tsx index 35ef56e1a..c6ecf3031 100644 --- a/examples/ping/src/components/LedgerSubmission.tsx +++ b/examples/ping/src/components/LedgerSubmission.tsx @@ -9,13 +9,13 @@ import { prettyjson } from '../utils' export function LedgerSubmission(props: { primaryParty?: string ledgerApiVersion?: string - status?: sdk.dappAPI.StatusEvent + connectResult?: sdk.dappAPI.ConnectResult }) { const { setErrorMsg } = useContext(ErrorContext) const [loading, setLoading] = useState(false) - const transactions = useTransactions(props.status) - const connected = props.status?.isConnected ?? false + const transactions = useTransactions(props.connectResult) + const connected = props.connectResult?.isConnected ?? false function createPingContract() { setErrorMsg('') diff --git a/examples/ping/src/components/PostEvents.tsx b/examples/ping/src/components/PostEvents.tsx index 7ff1994bb..8b92a87be 100644 --- a/examples/ping/src/components/PostEvents.tsx +++ b/examples/ping/src/components/PostEvents.tsx @@ -5,8 +5,10 @@ import { useAllEvents } from '../hooks/useAllEvents' import { prettyjson } from '../utils' import * as sdk from '@canton-network/dapp-sdk' -export function PostEvents(props: { status?: sdk.dappAPI.StatusEvent }) { - const events = useAllEvents(props.status) +export function PostEvents(props: { + connectResult?: sdk.dappAPI.ConnectResult +}) { + const events = useAllEvents(props.connectResult) const providerAvailable = window.canton const getEventColor = (type: string) => { diff --git a/examples/ping/src/components/Status.tsx b/examples/ping/src/components/Status.tsx index 78e0a0352..5b08459f5 100644 --- a/examples/ping/src/components/Status.tsx +++ b/examples/ping/src/components/Status.tsx @@ -7,11 +7,12 @@ export function Status(props: { return (

Status

- connected: {props.status?.isConnected ? '🟢' : '🔴'} + connected:{' '} + {props.status?.connection.isConnected ? '🟢' : '🔴'}
{props.status && (
- gateway: {props.status.kernel.id} + gateway: {props.status.provider.id} {props.status.network && (
@@ -21,9 +22,7 @@ export function Status(props: { <>
ledger API:{' '} - - {props.status.network.ledgerApi.baseUrl} - + {props.status.network.ledgerApi} )}
diff --git a/examples/ping/src/hooks/useAccounts.ts b/examples/ping/src/hooks/useAccounts.ts index 3b60f9798..37fa6c6eb 100644 --- a/examples/ping/src/hooks/useAccounts.ts +++ b/examples/ping/src/hooks/useAccounts.ts @@ -5,13 +5,13 @@ import { useContext, useEffect, useState } from 'react' import * as sdk from '@canton-network/dapp-sdk' import { ErrorContext } from '../ErrorContext' -export function useAccounts(status?: sdk.dappAPI.StatusEvent) { +export function useAccounts(connectResult?: sdk.dappAPI.ConnectResult) { const [accounts, setAccounts] = useState() const { setErrorMsg } = useContext(ErrorContext) useEffect(() => { - if (status?.isConnected) { + if (connectResult?.isConnected) { sdk.listAccounts() .then((accounts) => { setAccounts(accounts) @@ -23,10 +23,10 @@ export function useAccounts(status?: sdk.dappAPI.StatusEvent) { ) }) } - }, [status, setErrorMsg]) + }, [connectResult, setErrorMsg]) useEffect(() => { - if (status?.isConnected) { + if (connectResult?.isConnected) { const listener = (event: sdk.dappAPI.AccountsChangedEvent) => { console.log('[use-accounts] Accounts changed:', event) setAccounts(event) @@ -38,7 +38,7 @@ export function useAccounts(status?: sdk.dappAPI.StatusEvent) { sdk.removeOnAccountsChanged(listener) } } - }, [status, setAccounts]) + }, [connectResult, setAccounts]) return accounts } diff --git a/examples/ping/src/hooks/useAllEvents.ts b/examples/ping/src/hooks/useAllEvents.ts index 51ae90df8..05bc9fb7e 100644 --- a/examples/ping/src/hooks/useAllEvents.ts +++ b/examples/ping/src/hooks/useAllEvents.ts @@ -17,11 +17,11 @@ export type AllEvents = timestamp: Date } -export function useAllEvents(status?: sdk.dappAPI.StatusEvent) { +export function useAllEvents(connectResult?: sdk.dappAPI.ConnectResult) { const [events, setEvents] = useState([]) useEffect(() => { - if (status?.isConnected) { + if (connectResult?.isConnected) { const txListener = (event: sdk.dappAPI.TxChangedEvent) => { setEvents((prev) => [ { type: 'TxChanged', event, timestamp: new Date() }, @@ -55,7 +55,7 @@ export function useAllEvents(status?: sdk.dappAPI.StatusEvent) { sdk.removeOnAccountsChanged(accountsListener) } } - }, [status]) + }, [connectResult]) return events } diff --git a/examples/ping/src/hooks/useConnect.ts b/examples/ping/src/hooks/useConnect.ts index eac3b7851..570d8e311 100644 --- a/examples/ping/src/hooks/useConnect.ts +++ b/examples/ping/src/hooks/useConnect.ts @@ -9,20 +9,20 @@ import { handleErrorToast } from '@canton-network/core-wallet-ui-components' * React hook that manages the connection to the wallet gateway. * Uses the dapp-sdk to connect and disconnect, and updates the connection status. * - * @returns { connect, disconnect, status } + * @returns { connect, disconnect, connectResult } */ export function useConnect(): { connect: () => Promise disconnect: () => Promise - status?: sdk.dappAPI.StatusEvent + connectResult?: sdk.dappAPI.ConnectResult } { - const [status, setStatus] = useState() + const [connectResult, setConnectResult] = + useState() async function connect() { - sdk.connect() - .then((status) => { - setStatus(status) - }) + await sdk + .connect() + .then(setConnectResult) .catch((err) => { console.error('Error connecting to wallet:', err) handleErrorToast(err) @@ -31,42 +31,41 @@ export function useConnect(): { } async function disconnect() { - sdk.disconnect().then(() => { - setStatus(undefined) - }) + await sdk.disconnect() + setConnectResult(undefined) } useEffect(() => { sdk.status() - .then(setStatus) + .then((status) => setConnectResult(status.connection)) .catch(() => { - setStatus(undefined) + setConnectResult(undefined) }) }, []) useEffect(() => { - if (status?.isConnected) { + if (connectResult?.isConnected) { console.debug('[use-connect] Adding status changed listener') const onStatusChanged = (status: sdk.dappAPI.StatusEvent) => { console.debug( '[use-connect] Received status changed event:', status ) - setStatus(status) + setConnectResult(status.connection) } sdk.onStatusChanged(onStatusChanged) return () => { - console.debug('[use-connect] Removing status changed listener') + console.debug('[use-connect] Removing connect changed listener') sdk.removeOnStatusChanged(onStatusChanged) } } - }, [status]) + }, [connectResult]) return { connect, disconnect, - status, + connectResult, } } diff --git a/examples/ping/src/hooks/useStatus.ts b/examples/ping/src/hooks/useStatus.ts new file mode 100644 index 000000000..94462e449 --- /dev/null +++ b/examples/ping/src/hooks/useStatus.ts @@ -0,0 +1,56 @@ +// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { useEffect, useState } from 'react' +import * as sdk from '@canton-network/dapp-sdk' + +/** + * React hook that manages the connection to the wallet gateway. + * Uses the dapp-sdk to connect and disconnect, and updates the connection status. + * + * @returns { status, statusEvent } + */ +export function useStatus(): { + status: () => Promise + statusEvent?: sdk.dappAPI.StatusEvent +} { + const [statusEvent, setStatusEvent] = useState() + + async function status() { + await sdk + .status() + .then(setStatusEvent) + .catch(() => { + setStatusEvent(undefined) + }) + } + + useEffect(() => { + status() + }, []) + + useEffect(() => { + if (statusEvent?.connection.isConnected) { + console.debug('[use-status] Adding status changed listener') + const onStatusChanged = (status: sdk.dappAPI.StatusEvent) => { + console.debug( + '[use-status] Received status changed event:', + status + ) + setStatusEvent(status) + } + + sdk.onStatusChanged(onStatusChanged) + + return () => { + console.debug('[use-status] Removing status changed listener') + sdk.removeOnStatusChanged(onStatusChanged) + } + } + }, [statusEvent]) + + return { + status, + statusEvent, + } +} diff --git a/examples/ping/src/hooks/useTransactions.ts b/examples/ping/src/hooks/useTransactions.ts index 392e8b648..733ba5e71 100644 --- a/examples/ping/src/hooks/useTransactions.ts +++ b/examples/ping/src/hooks/useTransactions.ts @@ -4,13 +4,13 @@ import { useEffect, useState } from 'react' import * as sdk from '@canton-network/dapp-sdk' -export function useTransactions(status?: sdk.dappAPI.StatusEvent) { +export function useTransactions(connectResult?: sdk.dappAPI.ConnectResult) { const [transactions, setTransactions] = useState< sdk.dappAPI.TxChangedEvent[] >([]) useEffect(() => { - if (status?.isConnected) { + if (connectResult?.isConnected) { const listener = (event: sdk.dappAPI.TxChangedEvent) => { setTransactions((prevTxs) => [event, ...prevTxs]) } @@ -20,7 +20,7 @@ export function useTransactions(status?: sdk.dappAPI.StatusEvent) { sdk.removeOnTxChanged(listener) } } - }, [status, setTransactions]) + }, [connectResult, setTransactions]) return transactions } diff --git a/examples/ping/tests/example.spec.ts b/examples/ping/tests/example.spec.ts index 255ec0d63..24943be75 100644 --- a/examples/ping/tests/example.spec.ts +++ b/examples/ping/tests/example.spec.ts @@ -88,3 +88,153 @@ test('dApp: execute externally signed tx', async ({ }) ).toHaveCount(1) }) + +test('connection status handling edge cases', async ({ page: dappPage }) => { + const wg = new WalletGateway({ + dappPage, + openButton: (page) => + page.getByRole('button', { + name: 'open Wallet Gateway', + }), + connectButton: (page) => + page.getByRole('button', { + name: 'connect to Wallet Gateway', + }), + }) + await dappPage.goto('http://localhost:8080/') + + await expect(dappPage).toHaveTitle(/Example dApp/) + + const connectButton = dappPage.getByRole('button', { + name: 'connect to Wallet Gateway', + }) + const disconnectButton = dappPage.getByRole('button', { + name: 'disconnect', + }) + + // 1. Connect to a gateway -- ensure status is updated + await expect(connectButton).toBeVisible() + await wg.connect({ + customURL: `http://localhost:${dappApiPort}/api/v0/dapp`, + network: 'Local (OAuth IDP)', + }) + await expect(dappPage.getByText('Loading...')).toHaveCount(0) + await expect(disconnectButton).toBeVisible() + await expect(connectButton).not.toBeVisible() + + // 2. Hit disconnect button -- ensure status is updated + await expect(disconnectButton).toBeVisible() + await disconnectButton.click() + await expect(dappPage.getByText('Loading...')).toHaveCount(0) + await expect(connectButton).toBeVisible() + await expect(disconnectButton).not.toBeVisible() + + // 3. Reconnect + await wg.reconnect({ + customURL: `http://localhost:${dappApiPort}/api/v0/dapp`, + network: 'Local (OAuth IDP)', + }) + await expect(dappPage.getByText('Loading...')).toHaveCount(0) + await expect(disconnectButton).toBeVisible() + await expect(connectButton).not.toBeVisible() + + // 4. Hit logout button inside popup + await wg.logoutFromPopup() + await expect(connectButton).toBeVisible() + await expect(disconnectButton).not.toBeVisible() + + // 5. Reconnect + await wg.reconnect({ + customURL: `http://localhost:${dappApiPort}/api/v0/dapp`, + network: 'Local (OAuth IDP)', + }) + await expect(dappPage.getByText('Loading...')).toHaveCount(0) + await expect(disconnectButton).toBeVisible() + await expect(connectButton).not.toBeVisible() + + // 6. Refresh page -- ensure still connected & popup is closed + await dappPage.reload() + await expect(dappPage).toHaveTitle(/Example dApp/) + await expect(dappPage.getByText('Loading...')).toHaveCount(0) + await expect(disconnectButton).toBeVisible() + await expect(connectButton).not.toBeVisible() + // Verify popup is closed + const isPopupOpen = await wg.isPopupOpen() + expect(isPopupOpen).toBe(false) + + // 7. Open popup + await wg.openPopup() + const popupOpenAfterOpen = await wg.isPopupOpen() + expect(popupOpenAfterOpen).toBe(true) + // Verify still connected + await expect(disconnectButton).toBeVisible() + await expect(connectButton).not.toBeVisible() + + // 8. Close popup -- ensure still connected + await wg.closePopup() + await expect(disconnectButton).toBeVisible() + await expect(connectButton).not.toBeVisible() + + // 9. Disconnect while popup closed -- ensure disconnected + await expect(disconnectButton).toBeVisible() + await disconnectButton.click() + await expect(dappPage.getByText('Loading...')).toHaveCount(0) + await expect(connectButton).toBeVisible() + await expect(disconnectButton).not.toBeVisible() +}) + +test('popup opens with correct userUrl after reconnect', async ({ + page: dappPage, +}) => { + const wg = new WalletGateway({ + dappPage, + openButton: (page) => + page.getByRole('button', { + name: 'open Wallet Gateway', + }), + connectButton: (page) => + page.getByRole('button', { + name: 'connect to Wallet Gateway', + }), + }) + await dappPage.goto('http://localhost:8080/') + + await expect(dappPage).toHaveTitle(/Example dApp/) + + const connectButton = dappPage.getByRole('button', { + name: 'connect to Wallet Gateway', + }) + const disconnectButton = dappPage.getByRole('button', { + name: 'disconnect', + }) + + // 1. Login + await wg.connect({ + customURL: `http://localhost:${dappApiPort}/api/v0/dapp`, + network: 'Local (OAuth IDP)', + }) + await expect(dappPage.getByText('Loading...')).toHaveCount(0) + await expect(disconnectButton).toBeVisible() + await expect(connectButton).not.toBeVisible() + + // 2. Disconnect + await expect(disconnectButton).toBeVisible() + await disconnectButton.click() + await expect(dappPage.getByText('Loading...')).toHaveCount(0) + await expect(connectButton).toBeVisible() + await expect(disconnectButton).not.toBeVisible() + + // 3. Login again + await wg.reconnect({ + customURL: `http://localhost:${dappApiPort}/api/v0/dapp`, + network: 'Local (OAuth IDP)', + }) + await expect(dappPage.getByText('Loading...')).toHaveCount(0) + await expect(disconnectButton).toBeVisible() + await expect(connectButton).not.toBeVisible() + + // 4. Open wallet gateway and verify it opens with proper userUrl (not dApp URL) + await wg.closePopup() + await wg.openPopup() + await wg.waitForPopupUrl(new RegExp(`localhost:${dappApiPort}`)) +}) diff --git a/examples/portfolio/package.json b/examples/portfolio/package.json index b591e085d..7933d609f 100644 --- a/examples/portfolio/package.json +++ b/examples/portfolio/package.json @@ -1,6 +1,6 @@ { "name": "@canton-network/example-portfolio", - "version": "0.18.2", + "version": "0.19.0", "type": "module", "scripts": { "dev": "vite", diff --git a/examples/portfolio/playwright.config.ts b/examples/portfolio/playwright.config.ts index fd9bc7d75..d99e6db53 100644 --- a/examples/portfolio/playwright.config.ts +++ b/examples/portfolio/playwright.config.ts @@ -32,7 +32,8 @@ export default defineConfig({ // baseURL: 'http://localhost:3030', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', + trace: 'retain-on-failure', + video: 'retain-on-failure', }, /* Configure projects for major browsers */ @@ -42,10 +43,10 @@ export default defineConfig({ use: { ...devices['Desktop Chrome'] }, }, - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, - }, + // { + // name: 'firefox', + // use: { ...devices['Desktop Firefox'] }, + // }, // { // name: 'webkit', diff --git a/examples/portfolio/src/contexts/ConnectionProvider.tsx b/examples/portfolio/src/contexts/ConnectionProvider.tsx index 2947e1c26..b7418d401 100644 --- a/examples/portfolio/src/contexts/ConnectionProvider.tsx +++ b/examples/portfolio/src/contexts/ConnectionProvider.tsx @@ -19,6 +19,7 @@ export const ConnectionProvider: React.FC<{ children: React.ReactNode }> = ({ const connect = useCallback(() => { sdk.connect() + .then(() => sdk.status()) .then((status) => { setConnectionStatus(status) setAccounts([]) diff --git a/examples/portfolio/tests/example.spec.ts b/examples/portfolio/tests/example.spec.ts index 8909ddf19..5411d9bd8 100644 --- a/examples/portfolio/tests/example.spec.ts +++ b/examples/portfolio/tests/example.spec.ts @@ -48,6 +48,7 @@ const tap = async ( } test('two step transfer', async ({ page: dappPage }) => { + const rnd = Math.floor(Math.random() * 100000) const wg = new WalletGateway({ dappPage, openButton: (page) => @@ -66,12 +67,12 @@ test('two step transfer', async ({ page: dappPage }) => { await wg.connect({ network: 'LocalNet' }) const alice = await wg.createWalletIfNotExists({ - partyHint: 'alice', + partyHint: `alice-${rnd}`, signingProvider: 'participant', }) console.log('aliceParty', alice) const bob = await wg.createWalletIfNotExists({ - partyHint: 'bob', + partyHint: `bob-${rnd}`, signingProvider: 'participant', }) console.log('bobParty', bob) @@ -118,11 +119,13 @@ test('two step transfer', async ({ page: dappPage }) => { dappPage.getByRole('button', { name: 'Accept' }).first().click() ) await openTab(dappPage, 'Transaction History') - await expect(dappPage.getByText('Completed')).not.toHaveCount(0) - await expect(dappPage.getByText(message)).not.toHaveCount(0) + //transaction history is bugged, just disable this until we move to the new ui + //await expect(dappPage.getByText('Completed')).not.toHaveCount(0) + //await expect(dappPage.getByText(message)).not.toHaveCount(0) }) test('allocation', async ({ page: dappPage }) => { + const rnd = Math.floor(Math.random() * 100000) const wg = new WalletGateway({ dappPage, openButton: (page) => @@ -141,15 +144,15 @@ test('allocation', async ({ page: dappPage }) => { await wg.connect({ network: 'LocalNet' }) const venue = await wg.createWalletIfNotExists({ - partyHint: 'venue', + partyHint: `venue-${rnd}`, signingProvider: 'participant', }) const alice = await wg.createWalletIfNotExists({ - partyHint: 'alice', + partyHint: `alice-${rnd}`, signingProvider: 'participant', }) const bob = await wg.createWalletIfNotExists({ - partyHint: 'bob', + partyHint: `bob-${rnd}`, signingProvider: 'participant', }) diff --git a/package.json b/package.json index 31e612b69..9368e0d64 100644 --- a/package.json +++ b/package.json @@ -20,11 +20,12 @@ "test:all": "nx run-many -t test --parallel", "postinstall": "husky", "script:cleancoding": "tsx ./scripts/src/clean-coding.ts", - "script:install:daml-sdk": "tsx --eval \"import { installDamlSDK } from './scripts/src/install-daml-sdk.ts'; installDamlSDK()\"", + "script:install:dpm": "tsx --eval \"import { installDPM } from './scripts/src/install-dpm.ts'; installDPM()\"", "script:generate:openapi": "tsx ./scripts/src/generate-openapi-clients.ts", "script:generate:asyncapi": "tsx ./scripts/src/generate-asyncapi-clients.ts", "script:generate:protobufs": "tsx ./scripts/src/generate-protobufs.ts", "script:generate:tokenstandard": "tsx ./scripts/src/generate-token-standard.ts", + "script:generate:featured-dars": "tsx ./scripts/src/generate-featured-dars.ts", "script:fetch:canton": "tsx ./scripts/src/fetch-canton.ts", "script:fetch:splice": "tsx ./scripts/src/fetch-splice.ts", "script:fetch:localnet": "tsx ./scripts/src/fetch-localnet.ts", diff --git a/scripts/src/generate-asyncapi-clients.ts b/scripts/src/generate-asyncapi-clients.ts index d87251886..f84b46d33 100644 --- a/scripts/src/generate-asyncapi-clients.ts +++ b/scripts/src/generate-asyncapi-clients.ts @@ -3,7 +3,14 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { getRepoRoot, info, error } from './lib/utils.js' +import { + getRepoRoot, + info, + error, + Network, + SUPPORTED_VERSIONS, + getNetworkArg, +} from './lib/utils.js' import * as fs from 'fs' import * as path from 'path' import * as yaml from 'js-yaml' @@ -150,10 +157,10 @@ interface AsyncApiFileSpec { output: string } -const specs: AsyncApiFileSpec[] = [ +const specs = (cantonVersion: string): AsyncApiFileSpec[] => [ { - input: 'api-specs/ledger-api/3.4.7/asyncapi.yaml', - output: 'core/ledger-client/src/generated-clients/asyncapi-3.4.7.ts', + input: `api-specs/ledger-api/${cantonVersion}/asyncapi.yaml`, + output: `core/ledger-client-types/src/generated-clients/asyncapi-${cantonVersion}.ts`, }, ] @@ -296,12 +303,17 @@ async function generateAsyncApiClient( } } -async function main(specs: AsyncApiFileSpec[], root: string = process.cwd()) { +async function main(network: Network = 'devnet', root: string = process.cwd()) { + const cantonVersion = + SUPPORTED_VERSIONS[network].canton.version.split('-')[0] + await Promise.all( - specs.map((spec) => generateAsyncApiClient(spec, root)) + specs(cantonVersion).map((spec) => generateAsyncApiClient(spec, root)) ).then(() => console.log('Generated typescript clients for all async api specs') ) } -main(specs).catch((error) => console.log(error(`Fatal error: ${error}`))) +main(getNetworkArg()).catch((error) => + console.log(error(`Fatal error: ${error}`)) +) diff --git a/scripts/src/generate-featured-dars.ts b/scripts/src/generate-featured-dars.ts new file mode 100644 index 000000000..c3e481102 --- /dev/null +++ b/scripts/src/generate-featured-dars.ts @@ -0,0 +1,47 @@ +// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import * as path from 'path' +import { getRepoRoot, info } from './lib/utils.js' +import { installDPM } from './install-dpm.js' +import { generateDamlJsBindings } from './lib/daml-codegen.js' + +const repoRoot = getRepoRoot() + +const FEATURED_APP_PROXIES_CONFIG = { + sourceDir: path.join( + repoRoot, + '.splice/daml/splice-util-featured-app-proxies' + ), + destDir: path.join(repoRoot, 'damljs/featured-app-proxies'), + packageName: 'splice-util-featured-app-proxies', + version: '1.0.0', + dependencies: [ + path.join( + repoRoot, + '.splice/daml/dars/splice-api-token-holding-v1-1.0.0.dar' + ), + path.join( + repoRoot, + '.splice/daml/dars/splice-api-token-transfer-instruction-v1-1.0.0.dar' + ), + path.join( + repoRoot, + '.splice/daml/dars/splice-api-token-allocation-v1-1.0.0.dar' + ), + ], +} + +// TODO: this is a work in progress and should not currently be used +async function main() { + await installDPM() + + console.log(info('\n=== Generating Featured App Proxies bindings ===\n')) + await generateDamlJsBindings(FEATURED_APP_PROXIES_CONFIG) + + console.log( + info('\n=== All featured DAR bindings generated successfully ===\n') + ) +} + +main() diff --git a/scripts/src/generate-openapi-clients.ts b/scripts/src/generate-openapi-clients.ts index 573e859af..d90f9732b 100644 --- a/scripts/src/generate-openapi-clients.ts +++ b/scripts/src/generate-openapi-clients.ts @@ -117,15 +117,14 @@ async function generateOpenApiClient(spec: OpenApiSpec) { } } -const getSpecs = (spliceVersion: string): OpenApiSpec[] => [ +const getSpecs = ( + spliceVersion: string, + cantonVersion: string +): OpenApiSpec[] => [ // Canton JSON Ledger API { - input: 'api-specs/ledger-api/3.3.0/openapi.yaml', - output: 'core/ledger-client/src/generated-clients/openapi-3.3.0-SNAPSHOT.ts', - }, - { - input: 'api-specs/ledger-api/3.4.7/openapi.yaml', - output: 'core/ledger-client/src/generated-clients/openapi-3.4.7.ts', + input: `api-specs/ledger-api/${cantonVersion}/openapi.yaml`, + output: `core/ledger-client-types/src/generated-clients/openapi-${cantonVersion}.ts`, }, // Splice Scan API { @@ -164,9 +163,10 @@ async function main(network: Network = 'devnet') { await fetchSpliceSpecs(updateHash, network) Promise.all( - getSpecs(SUPPORTED_VERSIONS[network].splice.version).map( - generateOpenApiClient - ) + getSpecs( + SUPPORTED_VERSIONS[network].splice.version, + SUPPORTED_VERSIONS[network].canton.version.split('-')[0] + ).map(generateOpenApiClient) ).then(() => { console.log( success('Generated fresh TypeScript clients for all OpenAPI specs') diff --git a/scripts/src/generate-token-standard.ts b/scripts/src/generate-token-standard.ts index f60d53dd9..75310e5f0 100644 --- a/scripts/src/generate-token-standard.ts +++ b/scripts/src/generate-token-standard.ts @@ -2,68 +2,22 @@ // SPDX-License-Identifier: Apache-2.0 import * as path from 'path' -import { execSync } from 'child_process' -import { - getRepoRoot, - info, - warn, - error, - getAllFilesWithExtension, - ensureDir, - copyFileRecursive, -} from './lib/utils.js' -import { installDamlSDK } from './install-daml-sdk.js' +import { getRepoRoot } from './lib/utils.js' +import { installDPM } from './install-dpm.js' +import { generateDamlJsBindings } from './lib/daml-codegen.js' const repoRoot = getRepoRoot() -const SRC_DIR = path.join(repoRoot, '.splice/token-standard') -const DEST_DIR = path.join(repoRoot, 'damljs/token-standard-models') -async function main() { - console.log(info('Finding .daml files...')) - const damlFiles = getAllFilesWithExtension(SRC_DIR, '.daml') - - if (damlFiles.length === 0) { - console.log(warn('No .daml files found.')) - return - } - - await installDamlSDK() - - await ensureDir(DEST_DIR) - - console.log( - info(`Copying ${damlFiles.length} .daml files to ${DEST_DIR}...`) - ) - const copiedFiles: string[] = [] - for (const file of damlFiles) { - if (file.includes('test')) continue // Skip test files - const relativePath = path.relative(SRC_DIR, file) - const parts = relativePath.split(path.sep) - const newRelativePath = - parts.length > 1 ? path.join(...parts.slice(1)) : relativePath - const destPath = path.join(DEST_DIR, newRelativePath) - await ensureDir(path.dirname(destPath)) - await copyFileRecursive(file, destPath) - copiedFiles.push(destPath) - } - - console.log(info('Running "daml build"...')) - execSync('exec daml build', { - cwd: DEST_DIR, - stdio: 'inherit', - }) +const TOKEN_STANDARD_CONFIG = { + sourceDir: path.join(repoRoot, '.splice/token-standard'), + destDir: path.join(repoRoot, 'damljs/token-standard-models'), + packageName: 'token-standard-models', + version: '1.0.0', +} - console.log(info('Running "daml codegen js"...')) - try { - console.log(info(`exec daml codegen js`)) - execSync( - `exec daml codegen js .daml/dist/token-standard-models-1.0.0.dar -o .`, - { cwd: DEST_DIR, stdio: 'inherit' } - ) - console.log(info('Codegen completed.')) - } catch (err) { - console.error(error(`Error running daml codegen js: ${err}`)) - } +async function main() { + await installDPM() + await generateDamlJsBindings(TOKEN_STANDARD_CONFIG) } main() diff --git a/scripts/src/install-daml-sdk.ts b/scripts/src/install-daml-sdk.ts deleted file mode 100644 index c0520ac0f..000000000 --- a/scripts/src/install-daml-sdk.ts +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { execSync } from 'child_process' -import * as fs from 'fs' -import * as os from 'os' -import * as path from 'path' -import { - DAML_RELEASE_VERSION, - getRepoRoot, - info, - warn, - success, - error, - ensureDir, -} from './lib/utils.js' -import { pipeline } from 'stream/promises' -import { Readable } from 'stream' -import { ReadableStream } from 'stream/web' - -//this is done for comparison, the DAML_RELEASE_VERSION uses snapshot releases but the installed sdk included commit and might have a different minor version. -function compareDamlVersionWithInstalledSDK(daml_version: string): boolean { - const daml_installed = execSync('daml version', { encoding: 'utf8' }) - - function parseVersion(version: string) { - const match = version.match( - /^([0-9]+\.[0-9]+\.[0-9]+(?:-[A-Za-z0-9]+)?)(?:\.(\d+))?/ - ) - if (!match) throw new Error(`Invalid version format: ${version}`) - return { - prefix: match[1], - snapshot: match[2] ? parseInt(match[2], 10) : undefined, - } - } - - const parsed = parseVersion(daml_version) - - //we check if the sdk versions includes the major version of the requested - return daml_installed.includes(parsed.prefix) -} - -export async function installDamlSDK() { - if (compareDamlVersionWithInstalledSDK(DAML_RELEASE_VERSION)) { - console.log( - success( - `Daml SDK version ${DAML_RELEASE_VERSION} is already installed.` - ) - ) - return - } - - const TEMP_DIR = `${getRepoRoot()}/temp` - await ensureDir(TEMP_DIR) - - const osType = os.platform() - - const fetchAssetList = await fetch( - `https://api.github.com/repos/digital-asset/daml/releases/tags/v${DAML_RELEASE_VERSION}` - ) - - if (!fetchAssetList.ok) { - console.error( - error( - `Failed to fetch release information: ${fetchAssetList.statusText}` - ) - ) - process.exit(1) - } - - const assets = await fetchAssetList.json() - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const assetNames: string[] = assets.assets.map((a: any) => a.name) - const targetAsset = assetNames.find( - (name: string) => - name.startsWith('daml-sdk-') && name.endsWith(`${osType}.tar.gz`) - ) - - if (targetAsset === undefined) { - console.log( - warn( - `There is currently no daml sdk available for ${osType} in version ${DAML_RELEASE_VERSION}.` - ) - ) - console.log( - warn( - `Maybe you need to create a specific mapping for your OS in scripts/src/install-daml-sdk.ts?` - ) - ) - process.exit(1) - } - - const url = `https://github.com/digital-asset/daml/releases/download/v${DAML_RELEASE_VERSION}/${targetAsset}` - - const tarball = path.join(TEMP_DIR, 'daml-sdk.tar.gz') - console.log( - info(`== Downloading Daml SDK ${DAML_RELEASE_VERSION} for ${osType} ==`) - ) - console.log(info(`from: ${url}`)) - console.log(info(`to: ${tarball}`)) - console.log(info(`== This may take a while... ==`)) - - await (async () => { - const response = await fetch(url) - if (!response.ok) { - console.error( - error(`Failed to download tarball: ${response.statusText}`) - ) - process.exit(1) - } - await pipeline( - Readable.fromWeb(response.body as ReadableStream), - fs.createWriteStream(tarball) - ) - console.log( - info(`== Installing Daml SDK version: ${DAML_RELEASE_VERSION} ==`) - ) - execSync( - `daml install --install-assistant yes --install-with-internal-version yes "${tarball}"`, - { stdio: 'inherit' } - ) - - fs.rmSync(TEMP_DIR, { recursive: true, force: true }) - console.log(success('== Installation complete.')) - })() -} diff --git a/scripts/src/install-dpm.ts b/scripts/src/install-dpm.ts new file mode 100644 index 000000000..539ee516c --- /dev/null +++ b/scripts/src/install-dpm.ts @@ -0,0 +1,164 @@ +// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { execSync } from 'child_process' +import * as os from 'os' +import * as path from 'path' +import * as fs from 'fs' +import { + DAML_RELEASE_VERSION, + info, + success, + error, + warn, +} from './lib/utils.js' + +/** + * Ensure DPM is in PATH for the current process and future shells + */ +function ensureDpmInPath(): void { + const homeDir = os.homedir() + const dpmBinPath = path.join(homeDir, '.dpm', 'bin') + + // Check if dpm bin directory exists + if (!fs.existsSync(dpmBinPath)) { + return // DPM not installed yet + } + + // Add to current process PATH if not already there + const currentPath = process.env.PATH || '' + if (!currentPath.includes(dpmBinPath)) { + process.env.PATH = `${dpmBinPath}:${currentPath}` + console.log(info(`Added ${dpmBinPath} to PATH for current session`)) + } + + // Update shell config files for future sessions + const shellConfigFiles = [ + path.join(homeDir, '.bashrc'), + path.join(homeDir, '.zshrc'), + path.join(homeDir, '.profile'), + ] + + const pathExport = `export PATH="$HOME/.dpm/bin:$PATH"` + + for (const configFile of shellConfigFiles) { + if (fs.existsSync(configFile)) { + const content = fs.readFileSync(configFile, 'utf8') + + // Check if PATH export already exists + if ( + !content.includes('.dpm/bin') && + !content.includes('$HOME/.dpm/bin') + ) { + // Append to config file + fs.appendFileSync( + configFile, + `\n# Added by splice-wallet-kernel DPM installer\n${pathExport}\n` + ) + console.log( + info(`Updated ${configFile} to include DPM in PATH`) + ) + } + } + } +} + +/** + * Parse and compare DPM version with the desired version + */ +function compareDpmVersionWithDesired(desiredVersion: string): boolean { + try { + const dpmVersion = execSync('dpm version', { encoding: 'utf8' }) + + function parseVersion(version: string) { + const match = version.match( + /^([0-9]+\.[0-9]+\.[0-9]+(?:-[A-Za-z0-9]+)?)(?:\.(\d+))?/ + ) + if (!match) throw new Error(`Invalid version format: ${version}`) + return { + prefix: match[1], + snapshot: match[2] ? parseInt(match[2], 10) : undefined, + } + } + + const parsed = parseVersion(desiredVersion) + + // Check if the DPM version includes the major version of the requested + return dpmVersion.includes(parsed.prefix) + } catch (e) { + console.log(error(`Error checking DPM version: ${e}`)) + // DPM not installed + return false + } +} + +/** + * Install DPM (Daml Package Manager) + * DPM is the recommended way to manage Daml projects + */ +export async function installDPM() { + // First, ensure DPM is in PATH if it's already installed + ensureDpmInPath() + + if (compareDpmVersionWithDesired(DAML_RELEASE_VERSION)) { + console.log( + success(`DPM version ${DAML_RELEASE_VERSION} is already installed.`) + ) + return + } + + const osType = os.platform() + + console.log( + info( + `== Installing DPM (Daml Package Manager) version ${DAML_RELEASE_VERSION} for ${osType} ==` + ) + ) + + try { + // Install DPM using the official installation script + // The script automatically detects the OS and installs the appropriate version + if (osType === 'linux' || osType === 'darwin') { + console.log( + info('Downloading and running DPM installation script...') + ) + execSync( + `curl -sSL https://get.digitalasset.com/install/install.sh | sh -s ${DAML_RELEASE_VERSION}`, + { stdio: 'inherit' } + ) + + // After installation, ensure DPM is in PATH + ensureDpmInPath() + + console.log(success('== DPM installation complete ==')) + console.log( + warn( + 'Note: You may need to restart your terminal or run "source ~/.bashrc" (or ~/.zshrc) for PATH changes to take effect in new shells.' + ) + ) + } else if (osType === 'win32') { + console.log( + info( + 'For Windows, please install DPM manually from https://docs.digitalasset.com/build/3.4/dpm/dpm.html' + ) + ) + console.log(info('After installation, run: dpm install')) + process.exit(1) + } else { + console.log( + error( + `Unsupported OS: ${osType}. Please install DPM manually from https://docs.digitalasset.com/build/3.4/dpm/dpm.html` + ) + ) + process.exit(1) + } + } catch (err) { + console.error(error(`Failed to install DPM: ${err}`)) + console.log( + info( + 'Please install DPM manually from https://docs.digitalasset.com/build/3.4/dpm/dpm.html' + ) + ) + process.exit(1) + } +} diff --git a/scripts/src/lib/daml-codegen.ts b/scripts/src/lib/daml-codegen.ts new file mode 100644 index 000000000..751a9eb54 --- /dev/null +++ b/scripts/src/lib/daml-codegen.ts @@ -0,0 +1,177 @@ +// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import * as path from 'path' +import { execSync } from 'child_process' +import { + info, + warn, + error, + getAllFilesWithExtension, + ensureDir, + copyFileRecursive, +} from './utils.js' + +/** + * Configuration for a DAML codegen target + * Uses DPM (Daml Package Manager) for building and code generation + * See: https://docs.digitalasset.com/build/3.4/dpm/dpm.html + */ +export interface DamlCodegenConfig { + sourceDir: string + destDir: string + packageName: string + version: string +} + +/** + * Copy .daml files from source to destination, skipping test files + * and maintaining directory structure (minus first directory level) + */ +export async function copyDamlFiles( + sourceDir: string, + destDir: string +): Promise { + console.log(info('Finding .daml files...')) + const damlFiles = getAllFilesWithExtension(sourceDir, '.daml') + + if (damlFiles.length === 0) { + console.log(warn('No .daml files found.')) + return [] + } + + await ensureDir(destDir) + + console.log( + info(`Copying ${damlFiles.length} .daml files to ${destDir}...`) + ) + const copiedFiles: string[] = [] + for (const file of damlFiles) { + if (file.includes('test')) continue // Skip test files + const relativePath = path.relative(sourceDir, file) + const parts = relativePath.split(path.sep) + const newRelativePath = + parts.length > 1 ? path.join(...parts.slice(1)) : relativePath + const destPath = path.join(destDir, newRelativePath) + await ensureDir(path.dirname(destPath)) + await copyFileRecursive(file, destPath) + copiedFiles.push(destPath) + } + + return copiedFiles +} + +/** + * Run dpm build in the specified directory + * DPM (Daml Package Manager) replaces the legacy daml build command + */ +export function runDamlBuild(workingDir: string): void { + console.log(info('Running "dpm build"...')) + try { + // Capture stdout/stderr to check for SDK_NOT_INSTALLED + const output = execSync('dpm build', { + cwd: workingDir, + encoding: 'utf-8', + }) + console.log(output) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (err: any) { + // Capture stdout/stderr from the error + const stdout = err.stdout?.toString() || '' + const stderr = err.stderr?.toString() || '' + const combinedOutput = stdout + stderr + + // Display the output + if (stdout) console.log(stdout) + if (stderr) console.error(stderr) + + // Check if SDK is not installed + if (combinedOutput.includes('SDK_NOT_INSTALLED')) { + console.log(warn('SDK not installed, attempting to install...')) + + // Extract the install command from the output + // Pattern: "via 'dpm install X.X.X...'" + const installMatch = combinedOutput.match( + /via\s+'dpm install ([^']+)'/ + ) + + if (installMatch && installMatch[1]) { + const version = installMatch[1] + console.log(info(`Installing SDK version: ${version}`)) + + try { + execSync(`dpm install ${version}`, { + cwd: workingDir, + stdio: 'inherit', + }) + + console.log(info('SDK installed, retrying build...')) + execSync('dpm build', { + cwd: workingDir, + stdio: 'inherit', + }) + return + } catch (installErr) { + console.error( + error( + `Failed to install SDK or retry build: ${installErr}` + ) + ) + throw installErr + } + } else { + console.error( + error( + 'Could not extract install command from error message' + ) + ) + } + } + + // Re-throw if not SDK_NOT_INSTALLED or if we couldn't handle it + throw err + } +} + +/** + * Run dpm codegen js for a DAR file + * Generates JavaScript/TypeScript bindings from compiled DAR + */ +export function runDamlCodegen(workingDir: string, darFileName: string): void { + console.log(info('Running "dpm codegen-js"...')) + try { + console.log(info(`dpm codegen-js`)) + execSync(`dpm codegen-js .daml/dist/${darFileName} -o .`, { + cwd: workingDir, + stdio: 'inherit', + }) + console.log(info('Codegen completed.')) + } catch (err) { + console.error(error(`Error running dpm codegen js: ${err}`)) + throw err + } +} + +/** + * Generate DAML JavaScript bindings from source .daml files + * Uses DPM (Daml Package Manager) for the complete workflow: + * 1. Copy .daml files to destination + * 2. Copy dependency DARs if specified + * 3. Build DAR with dpm build + * 4. Generate JS bindings with dpm codegen js + */ +export async function generateDamlJsBindings( + config: DamlCodegenConfig +): Promise { + const copiedFiles = await copyDamlFiles(config.sourceDir, config.destDir) + + if (copiedFiles.length === 0) { + console.log(warn('No files to process. Skipping build and codegen.')) + return + } + + runDamlBuild(config.destDir) + + const darFileName = `${config.packageName}-${config.version}.dar` + runDamlCodegen(config.destDir, darFileName) +} diff --git a/scripts/src/lib/version-config.json b/scripts/src/lib/version-config.json index 816ea4778..bdbaae1a4 100644 --- a/scripts/src/lib/version-config.json +++ b/scripts/src/lib/version-config.json @@ -1,5 +1,5 @@ { - "DAML_RELEASE_VERSION": "3.4.11-snapshot.20260127.17528.0.ve786203c", + "DAML_RELEASE_VERSION": "3.4.9", "SUPPORTED_VERSIONS": { "devnet": { "canton": { diff --git a/scripts/src/upgrade-splice.ts b/scripts/src/upgrade-splice.ts index abf5330d4..df73b90b3 100644 --- a/scripts/src/upgrade-splice.ts +++ b/scripts/src/upgrade-splice.ts @@ -117,6 +117,7 @@ const scripts = [ 'fetch-localnet.ts', 'fetch-canton.ts', 'generate-openapi-clients.ts', + 'generate-asyncapi-clients.ts', ] for (const script of scripts) { try { diff --git a/sdk/dapp-sdk/src/dapp-api/rpc-gen/typings.ts b/sdk/dapp-sdk/src/dapp-api/rpc-gen/typings.ts index e8c813aae..12cb2bcae 100644 --- a/sdk/dapp-sdk/src/dapp-api/rpc-gen/typings.ts +++ b/sdk/dapp-sdk/src/dapp-api/rpc-gen/typings.ts @@ -95,19 +95,25 @@ export type Resource = string export type Body = string /** * - * The unique identifier of the Wallet Gateway. + * The unique identifier of the Provider. * */ export type Id = string /** * - * The type of client that implements the Wallet Gateway. + * The version of the Provider. * */ -export type ClientType = 'browser' | 'desktop' | 'mobile' | 'remote' +export type Version = string /** * - * The URL of the Wallet Gateway. + * The type of client that implements the Provider. + * + */ +export type ProviderType = 'browser' | 'desktop' | 'mobile' | 'remote' +/** + * + * The URL of the Wallet Provider. * */ export type Url = string @@ -119,12 +125,13 @@ export type Url = string export type UserUrl = string /** * - * Represents a Wallet Gateway. + * Represents a Provider. * */ -export interface KernelInfo { +export interface Provider { id: Id - clientType: ClientType + version?: Version + providerType?: ProviderType url?: Url userUrl?: UserUrl [k: string]: any @@ -135,6 +142,12 @@ export interface KernelInfo { * */ export type IsConnected = boolean +/** + * + * Reason for the wallet state, e.g., 'no signing provider matched'. + * + */ +export type Reason = string /** * * Whether or not a connection to a network is established. @@ -147,6 +160,13 @@ export type IsNetworkConnected = boolean * */ export type NetworkReason = string +export interface ConnectResult { + isConnected: IsConnected + reason?: Reason + isNetworkConnected: IsNetworkConnected + networkReason?: NetworkReason + [k: string]: any +} /** * * The network ID the wallet corresponds to. @@ -158,16 +178,13 @@ export type NetworkId = string * The base URL of the ledger API. * */ -export type BaseUrl = string +export type LedgerApiUrl = string /** * - * Ledger API configuration. + * JWT authentication token. * */ -export interface LedgerApiConfig { - baseUrl: BaseUrl - [k: string]: any -} +export type AccessToken = string /** * * Network information, if connected to a network. @@ -175,15 +192,10 @@ export interface LedgerApiConfig { */ export interface Network { networkId: NetworkId - ledgerApi?: LedgerApiConfig + ledgerApi?: LedgerApiUrl + accessToken?: AccessToken [k: string]: any } -/** - * - * JWT authentication token. - * - */ -export type AccessToken = string /** * * The user identifier. @@ -299,12 +311,6 @@ export type TopologyTransactions = string * */ export type Disabled = boolean -/** - * - * Reason for the wallet state, e.g., 'no signing provider matched'. - * - */ -export type Reason = string /** * * Structure representing a wallet @@ -423,10 +429,8 @@ export interface LedgerApiParams { [k: string]: any } export interface StatusEvent { - kernel: KernelInfo - isConnected: IsConnected - isNetworkConnected: IsNetworkConnected - networkReason?: NetworkReason + provider: Provider + connection: ConnectResult network?: Network session?: Session [k: string]: any @@ -488,7 +492,7 @@ export type TxChangedEvent = */ export type Status = () => Promise -export type Connect = () => Promise +export type Connect = () => Promise export type Disconnect = () => Promise export type GetActiveNetwork = () => Promise export type PrepareExecute = (params: PrepareExecuteParams) => Promise diff --git a/sdk/dapp-sdk/src/listener.ts b/sdk/dapp-sdk/src/listener.ts index 60c9857cc..d7c7974fb 100644 --- a/sdk/dapp-sdk/src/listener.ts +++ b/sdk/dapp-sdk/src/listener.ts @@ -8,7 +8,7 @@ import { WalletEvent } from '@canton-network/core-types' if (window.canton) { // Clean up session on disconnect onStatusChanged(async (event) => { - if (!event.isConnected) { + if (!event.connection.isConnected) { clearAllLocalState({ closePopup: true }) } }) diff --git a/sdk/dapp-sdk/src/provider.ts b/sdk/dapp-sdk/src/provider.ts index 358aed7e8..74f5444ab 100644 --- a/sdk/dapp-sdk/src/provider.ts +++ b/sdk/dapp-sdk/src/provider.ts @@ -23,7 +23,6 @@ import { Network, Session, SignMessageResult, - StatusEvent, Wallet, } from './dapp-api/rpc-gen/typings' import { popup } from '@canton-network/core-wallet-ui-components' @@ -115,16 +114,17 @@ const withTimeout = ( // Remote dApp API Server which wraps the Remote-dApp API Server with promises export const dappController = (provider: SpliceProvider) => buildController({ - connect: async (): Promise => { - const response = await provider.request({ - method: 'connect', - }) + connect: async (): Promise => { + const response = + await provider.request({ + method: 'connect', + }) if (response.session) { return response } else { popup.open(response.userUrl ?? '') - const promise = new Promise( + const promise = new Promise( (resolve, reject) => { // 5 minutes timeout const timeout = withTimeout( @@ -135,15 +135,14 @@ export const dappController = (provider: SpliceProvider) => provider.on( 'statusChanged', (event) => { - if (event.isConnected) { + if (event.connection.isConnected) { clearTimeout(timeout) - resolve(event) + resolve(event.connection) } } ) } ) - return promise } }, diff --git a/sdk/dapp-sdk/src/provider/request.ts b/sdk/dapp-sdk/src/provider/request.ts index b08e54cea..ebf7f7b8c 100644 --- a/sdk/dapp-sdk/src/provider/request.ts +++ b/sdk/dapp-sdk/src/provider/request.ts @@ -17,7 +17,7 @@ interface ConnectOptions { export async function connect( options?: ConnectOptions -): Promise { +): Promise { const { defaultGateways = gateways, additionalGateways = [] } = options || {} @@ -34,17 +34,20 @@ export async function connect( storage.setKernelDiscovery(result) const provider = injectProvider(result) - const response = await provider.request({ - method: 'connect', + // Store token once connect fires a statusChanged event + provider.on('statusChanged', (event) => { + if (event.connection.isConnected) { + if (event.session) { + storage.setKernelSession(event) + } else { + console.warn('SDK: Connected without session', event) + } + } }) - if (response.session) { - storage.setKernelSession(response) - } else { - console.warn('SDK: Connected without session', response) - } - - return response + return await provider.request({ + method: 'connect', + }) }) .catch((err) => { let details = '' diff --git a/sdk/wallet-sdk/package.json b/sdk/wallet-sdk/package.json index 885ac2d1b..fab922240 100644 --- a/sdk/wallet-sdk/package.json +++ b/sdk/wallet-sdk/package.json @@ -1,7 +1,7 @@ { "name": "@canton-network/wallet-sdk", "type": "module", - "version": "0.20.0", + "version": "0.21.0", "description": "Node/browser SDK for integrating with Canton Network", "author": "Marc Juchli ", "license": "Apache-2.0", @@ -24,7 +24,9 @@ "test": "echo \"Warning: no test specified\"" }, "dependencies": { + "@canton-network/core-asyncapi-client": "workspace:^", "@canton-network/core-ledger-client": "workspace:^", + "@canton-network/core-ledger-client-types": "workspace:^", "@canton-network/core-ledger-proto": "workspace:^", "@canton-network/core-signing-lib": "workspace:^", "@canton-network/core-splice-client": "workspace:^", diff --git a/sdk/wallet-sdk/src/ledgerController.ts b/sdk/wallet-sdk/src/ledgerController.ts index 34cb1c23b..b3aa3e1ed 100644 --- a/sdk/wallet-sdk/src/ledgerController.ts +++ b/sdk/wallet-sdk/src/ledgerController.ts @@ -12,12 +12,13 @@ import { AllocateExternalPartyResponse, JSContractEntry, isJsCantonError, - components, - WebSocketClient, + UserSchema, JsGetUpdatesResponse, CompletionResponse, PrepareSubmissionResponse, + defaultRetryableOptions, } from '@canton-network/core-ledger-client' +import { WebSocketClient } from '@canton-network/core-asyncapi-client' import { signTransactionHash, getPublicKeyFromPrivate, @@ -31,7 +32,6 @@ import { pino } from 'pino' import { SigningPublicKey } from '@canton-network/core-ledger-proto' import { TopologyController } from './topologyController.js' import { PartyId } from '@canton-network/core-types' -import { defaultRetryableOptions } from '@canton-network/core-ledger-client' import { AccessTokenProvider } from '@canton-network/core-wallet-auth' import { decodeTopologyTransaction } from '@canton-network/core-tx-visualizer' @@ -108,7 +108,6 @@ export class LedgerController { isAdmin, logger: this.logger, accessTokenProvider, - wsSupportBackOff: 6000 * 10, }) this.webSocketManager = new WebSocketManager({ @@ -1309,7 +1308,7 @@ export class LedgerController { public async createUser( userId: string, primaryParty: PartyId - ): Promise { + ): Promise { if (!this.isAdmin) { throw new Error('Use adminLedger to call createUser') } diff --git a/sdk/wallet-sdk/src/tokenStandardController.ts b/sdk/wallet-sdk/src/tokenStandardController.ts index f0ee2f6b1..bfd170445 100644 --- a/sdk/wallet-sdk/src/tokenStandardController.ts +++ b/sdk/wallet-sdk/src/tokenStandardController.ts @@ -14,8 +14,8 @@ import { Holding, ExerciseCommand, DisclosedContract, - WebSocketClient, } from '@canton-network/core-ledger-client' +import { WebSocketClient } from '@canton-network/core-asyncapi-client' import { WebSocketManager } from './webSocketManager.js' import { ScanClient, ScanProxyClient } from '@canton-network/core-splice-client' @@ -153,7 +153,6 @@ export class TokenStandardController { isAdmin, logger: this.logger, accessTokenProvider, - wsSupportBackOff: 6000 * 10, }) this.webSocketManager = new WebSocketManager({ @@ -332,6 +331,7 @@ export class TokenStandardController { * @param limit optional limit for number of UTXOs to return. * @param offset optional offset to list utxos from, default is latest. * @param party optional party to list utxos + * @param continueUntilCompletion optional search the whole ledger for active contracts. Use only when the amount of contracts exceeds the limit defined in http-list-max-elements-limit * @returns A promise that resolves to an array of holding UTXOs. */ @@ -339,27 +339,29 @@ export class TokenStandardController { includeLocked: boolean = true, limit?: number, offset?: number, - party?: PartyId + party?: PartyId, + continueUntilCompletion?: boolean ): Promise[]> { const utxos = await this.service.listContractsByInterface( HOLDING_INTERFACE_ID, party ?? this.getPartyId(), limit, - offset + offset, + continueUntilCompletion ) const currentTime = new Date() - if (includeLocked) { - return utxos - } else { - return utxos.filter( - (utxo) => - !TokenStandardService.isHoldingLocked( - utxo.interfaceViewValue, - currentTime - ) - ) - } + const filteredUtxos = includeLocked + ? utxos + : utxos.filter( + (utxo) => + !TokenStandardService.isHoldingLocked( + utxo.interfaceViewValue, + currentTime + ) + ) + + return filteredUtxos } /** @@ -675,9 +677,9 @@ export class TokenStandardController { const ledgerEnd = await this.client.get('/v2/state/ledger-end') - const utxos = inputUtxos?.length - ? inputUtxos - : await this.listHoldingUtxos(true, 100, undefined, walletParty) + const utxos = + inputUtxos ?? + (await this.listHoldingUtxos(true, 100, undefined, walletParty)) if (utxos.length < 10) { throw new Error(`Utxos are less than 10, found ${utxos.length}`) diff --git a/sdk/wallet-sdk/src/webSocketManager.ts b/sdk/wallet-sdk/src/webSocketManager.ts index 6683a84b2..73dbd4f9a 100644 --- a/sdk/wallet-sdk/src/webSocketManager.ts +++ b/sdk/wallet-sdk/src/webSocketManager.ts @@ -1,10 +1,8 @@ // Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -import { - JsGetUpdatesResponse, - WebSocketClient, -} from '@canton-network/core-ledger-client' +import { WebSocketClient } from '@canton-network/core-asyncapi-client' +import { JsGetUpdatesResponse } from '@canton-network/core-ledger-client-types' import { PartyId } from '@canton-network/core-types' import { Logger } from 'pino' diff --git a/wallet-gateway/extension/src/dapp-api/controller.ts b/wallet-gateway/extension/src/dapp-api/controller.ts index 2bcd899ff..81a189204 100644 --- a/wallet-gateway/extension/src/dapp-api/controller.ts +++ b/wallet-gateway/extension/src/dapp-api/controller.ts @@ -7,7 +7,6 @@ import Browser from 'webextension-polyfill' import buildController from './rpc-gen' import { - KernelInfo, LedgerApiParams, Network, PrepareExecuteParams, @@ -18,31 +17,15 @@ import { import { Store } from '@canton-network/core-wallet-store' -const kernelInfo: KernelInfo = { - id: 'default-kernel-id', - clientType: 'browser', -} - // TODO: Make store required export const dappController = (store?: Store) => buildController({ connect: async () => Promise.resolve({ - kernel: kernelInfo, - isConnected: false, - isNetworkConnected: false, - networkReason: 'Unauthenticated', - userUrl: Browser.runtime.getURL('pages/user.html'), - network: { - networkId: 'default-network-id', - ledgerApi: { - baseUrl: 'http://default-ledger-api', - }, - }, - session: { - accessToken: 'default-access-token', - userId: 'default-user-id', - }, + isConnected: true, + reason: 'OK', + isNetworkConnected: true, + networkReason: 'OK', }), disconnect: async () => Promise.resolve(null), ledgerApi: async (params: LedgerApiParams) => diff --git a/wallet-gateway/extension/src/dapp-api/rpc-gen/typings.ts b/wallet-gateway/extension/src/dapp-api/rpc-gen/typings.ts index e8c813aae..12cb2bcae 100644 --- a/wallet-gateway/extension/src/dapp-api/rpc-gen/typings.ts +++ b/wallet-gateway/extension/src/dapp-api/rpc-gen/typings.ts @@ -95,19 +95,25 @@ export type Resource = string export type Body = string /** * - * The unique identifier of the Wallet Gateway. + * The unique identifier of the Provider. * */ export type Id = string /** * - * The type of client that implements the Wallet Gateway. + * The version of the Provider. * */ -export type ClientType = 'browser' | 'desktop' | 'mobile' | 'remote' +export type Version = string /** * - * The URL of the Wallet Gateway. + * The type of client that implements the Provider. + * + */ +export type ProviderType = 'browser' | 'desktop' | 'mobile' | 'remote' +/** + * + * The URL of the Wallet Provider. * */ export type Url = string @@ -119,12 +125,13 @@ export type Url = string export type UserUrl = string /** * - * Represents a Wallet Gateway. + * Represents a Provider. * */ -export interface KernelInfo { +export interface Provider { id: Id - clientType: ClientType + version?: Version + providerType?: ProviderType url?: Url userUrl?: UserUrl [k: string]: any @@ -135,6 +142,12 @@ export interface KernelInfo { * */ export type IsConnected = boolean +/** + * + * Reason for the wallet state, e.g., 'no signing provider matched'. + * + */ +export type Reason = string /** * * Whether or not a connection to a network is established. @@ -147,6 +160,13 @@ export type IsNetworkConnected = boolean * */ export type NetworkReason = string +export interface ConnectResult { + isConnected: IsConnected + reason?: Reason + isNetworkConnected: IsNetworkConnected + networkReason?: NetworkReason + [k: string]: any +} /** * * The network ID the wallet corresponds to. @@ -158,16 +178,13 @@ export type NetworkId = string * The base URL of the ledger API. * */ -export type BaseUrl = string +export type LedgerApiUrl = string /** * - * Ledger API configuration. + * JWT authentication token. * */ -export interface LedgerApiConfig { - baseUrl: BaseUrl - [k: string]: any -} +export type AccessToken = string /** * * Network information, if connected to a network. @@ -175,15 +192,10 @@ export interface LedgerApiConfig { */ export interface Network { networkId: NetworkId - ledgerApi?: LedgerApiConfig + ledgerApi?: LedgerApiUrl + accessToken?: AccessToken [k: string]: any } -/** - * - * JWT authentication token. - * - */ -export type AccessToken = string /** * * The user identifier. @@ -299,12 +311,6 @@ export type TopologyTransactions = string * */ export type Disabled = boolean -/** - * - * Reason for the wallet state, e.g., 'no signing provider matched'. - * - */ -export type Reason = string /** * * Structure representing a wallet @@ -423,10 +429,8 @@ export interface LedgerApiParams { [k: string]: any } export interface StatusEvent { - kernel: KernelInfo - isConnected: IsConnected - isNetworkConnected: IsNetworkConnected - networkReason?: NetworkReason + provider: Provider + connection: ConnectResult network?: Network session?: Session [k: string]: any @@ -488,7 +492,7 @@ export type TxChangedEvent = */ export type Status = () => Promise -export type Connect = () => Promise +export type Connect = () => Promise export type Disconnect = () => Promise export type GetActiveNetwork = () => Promise export type PrepareExecute = (params: PrepareExecuteParams) => Promise diff --git a/wallet-gateway/remote/src/dapp-api/controller.ts b/wallet-gateway/remote/src/dapp-api/controller.ts index 1dadb3f66..0f00db6d9 100644 --- a/wallet-gateway/remote/src/dapp-api/controller.ts +++ b/wallet-gateway/remote/src/dapp-api/controller.ts @@ -9,7 +9,6 @@ import { PrepareExecuteParams, SignMessageResult, StatusEvent, - StatusEventAsync, Wallet, } from './rpc-gen/typings.js' import { Store, Transaction } from '@canton-network/core-wallet-store' @@ -40,7 +39,6 @@ export const dappController = ( connect: async () => { if (!context || !(await store.getSession())) { return { - kernel: kernelInfo, isConnected: false, isNetworkConnected: false, networkReason: 'Unauthenticated', @@ -58,16 +56,26 @@ export const dappController = ( }) const status = await networkStatus(ledgerClient) const notifier = notificationService.getNotifier(context.userId) - const StatusEvent: StatusEvent = { - kernel: kernelInfo, + const provider = { + id: kernelInfo.id, + version: 'TODO', + providerType: kernelInfo.clientType, + url: dappUrl, + userUrl: `${userUrl}/login/`, + } + const connection = { isConnected: true, + reason: 'OK', isNetworkConnected: status.isConnected, networkReason: status.reason ? status.reason : 'OK', + } + const statusEvent = { + provider: provider, + connection: connection, network: { networkId: network.id, - ledgerApi: { - baseUrl: network.ledgerApi.baseUrl, - }, + ledgerApi: network.ledgerApi.baseUrl, + accessToken: context.accessToken, }, session: { id: session?.id, @@ -76,8 +84,8 @@ export const dappController = ( }, userUrl: `${userUrl}/login/`, } - notifier.emit('statusChanged', StatusEvent) - return StatusEvent as StatusEventAsync + notifier.emit('statusChanged', statusEvent as StatusEvent) + return connection }, disconnect: async () => { if (!context) { @@ -86,11 +94,18 @@ export const dappController = ( const notifier = notificationService.getNotifier(context.userId) await store.removeSession() notifier.emit('statusChanged', { - kernel: kernelInfo, - isConnected: false, - isNetworkConnected: false, - networkReason: 'disconnect', - userUrl: `${userUrl}/login/`, + provider: { + id: kernelInfo.id, + providerType: kernelInfo.clientType, + url: dappUrl, + userUrl: `${userUrl}/login/`, + }, + connection: { + isConnected: false, + reason: 'disconnect', + isNetworkConnected: false, + networkReason: 'disconnect', + }, } as StatusEvent) } @@ -185,12 +200,22 @@ export const dappController = ( } }, status: async () => { + const provider = { + id: kernelInfo.id, + version: 'TODO', + providerType: kernelInfo.clientType, + url: dappUrl, + userUrl: `${userUrl}/login/`, + } if (!context || !(await store.getSession())) { return { - kernel: kernelInfo, - isConnected: false, - isNetworkConnected: false, - networkReason: 'Unauthenticated', + provider: provider, + connection: { + isConnected: false, + reason: 'Unauthenticated', + isNetworkConnected: false, + networkReason: 'Unauthenticated', + }, } } @@ -203,16 +228,19 @@ export const dappController = ( accessToken: context.accessToken, }) const status = await networkStatus(ledgerClient) + return { - kernel: kernelInfo, - isConnected: true, - isNetworkConnected: status.isConnected, - networkReason: status.reason ? status.reason : 'OK', + provider: provider, + connection: { + isConnected: true, + reason: 'OK', + isNetworkConnected: status.isConnected, + networkReason: status.reason ? status.reason : 'OK', + }, network: { networkId: network.id, - ledgerApi: { - baseUrl: network.ledgerApi.baseUrl, - }, + ledgerApi: network.ledgerApi.baseUrl, + accessToken: context.accessToken, }, session: { id: session?.id, @@ -220,7 +248,7 @@ export const dappController = ( userId: context.userId, }, userUrl: `${userUrl}/login/`, - } as StatusEventAsync + } }, connected: async () => { throw new Error('Only for events.') diff --git a/wallet-gateway/remote/src/dapp-api/rpc-gen/typings.ts b/wallet-gateway/remote/src/dapp-api/rpc-gen/typings.ts index ac3d31652..e4681f515 100644 --- a/wallet-gateway/remote/src/dapp-api/rpc-gen/typings.ts +++ b/wallet-gateway/remote/src/dapp-api/rpc-gen/typings.ts @@ -95,19 +95,25 @@ export type Resource = string export type Body = string /** * - * The unique identifier of the Wallet Gateway. + * The unique identifier of the Provider. * */ export type Id = string /** * - * The type of client that implements the Wallet Gateway. + * The version of the Provider. * */ -export type ClientType = 'browser' | 'desktop' | 'mobile' | 'remote' +export type Version = string /** * - * The URL of the Wallet Gateway. + * The type of client that implements the Provider. + * + */ +export type ProviderType = 'browser' | 'desktop' | 'mobile' | 'remote' +/** + * + * The URL of the Wallet Provider. * */ export type Url = string @@ -119,12 +125,13 @@ export type Url = string export type UserUrl = string /** * - * Represents a Wallet Gateway. + * Represents a Provider. * */ -export interface KernelInfo { +export interface Provider { id: Id - clientType: ClientType + version?: Version + providerType?: ProviderType url?: Url userUrl?: UserUrl [k: string]: any @@ -135,6 +142,12 @@ export interface KernelInfo { * */ export type IsConnected = boolean +/** + * + * Reason for the wallet state, e.g., 'no signing provider matched'. + * + */ +export type Reason = string /** * * Whether or not a connection to a network is established. @@ -147,6 +160,13 @@ export type IsNetworkConnected = boolean * */ export type NetworkReason = string +export interface ConnectResult { + isConnected: IsConnected + reason?: Reason + isNetworkConnected: IsNetworkConnected + networkReason?: NetworkReason + [k: string]: any +} /** * * The network ID the wallet corresponds to. @@ -158,16 +178,13 @@ export type NetworkId = string * The base URL of the ledger API. * */ -export type BaseUrl = string +export type LedgerApiUrl = string /** * - * Ledger API configuration. + * JWT authentication token. * */ -export interface LedgerApiConfig { - baseUrl: BaseUrl - [k: string]: any -} +export type AccessToken = string /** * * Network information, if connected to a network. @@ -175,15 +192,10 @@ export interface LedgerApiConfig { */ export interface Network { networkId: NetworkId - ledgerApi?: LedgerApiConfig + ledgerApi?: LedgerApiUrl + accessToken?: AccessToken [k: string]: any } -/** - * - * JWT authentication token. - * - */ -export type AccessToken = string /** * * The user identifier. @@ -200,19 +212,6 @@ export interface Session { userId: UserId [k: string]: any } -export interface StatusEvent { - kernel: KernelInfo - isConnected: IsConnected - isNetworkConnected: IsNetworkConnected - networkReason?: NetworkReason - network?: Network - session?: Session - [k: string]: any -} -export interface ConnectResult { - userUrl: UserUrl - [k: string]: any -} /** * * The signature of the transaction. @@ -280,12 +279,6 @@ export type TopologyTransactions = string * */ export type Disabled = boolean -/** - * - * Reason for the wallet state, e.g., 'no signing provider matched'. - * - */ -export type Reason = string /** * * Structure representing a wallet @@ -435,7 +428,13 @@ export interface LedgerApiParams { body?: Body [k: string]: any } -export type StatusEventAsync = StatusEvent & ConnectResult +export interface StatusEvent { + provider: Provider + connection: ConnectResult + network?: Network + session?: Session + [k: string]: any +} /** * * Represents a null value, used in responses where no data is returned. @@ -493,7 +492,7 @@ export type TxChangedEvent = */ export type Status = () => Promise -export type Connect = () => Promise +export type Connect = () => Promise export type Disconnect = () => Promise export type GetActiveNetwork = () => Promise export type PrepareExecute = ( diff --git a/wallet-gateway/remote/src/dapp-api/server.test.ts b/wallet-gateway/remote/src/dapp-api/server.test.ts index 3280378ab..f448eff79 100644 --- a/wallet-gateway/remote/src/dapp-api/server.test.ts +++ b/wallet-gateway/remote/src/dapp-api/server.test.ts @@ -60,10 +60,6 @@ test('call connect rpc', async () => { id: 0, jsonrpc: '2.0', result: { - kernel: { - id: 'remote-da', - clientType: 'remote', - }, isConnected: false, isNetworkConnected: false, networkReason: 'Unauthenticated', diff --git a/wallet-gateway/remote/src/user-api/controller.ts b/wallet-gateway/remote/src/user-api/controller.ts index 5fc76dbc2..0be51a998 100644 --- a/wallet-gateway/remote/src/user-api/controller.ts +++ b/wallet-gateway/remote/src/user-api/controller.ts @@ -72,6 +72,12 @@ export const userController = ( _logger: Logger ) => { const logger = _logger.child({ component: 'user-controller' }) + const provider = { + id: kernelInfo.id, + version: 'TODO', + providerType: kernelInfo.clientType, + userUrl: `${userUrl}/login/`, + } return buildController({ addNetwork: async (params: AddNetworkParams) => { @@ -467,9 +473,9 @@ export const userController = ( removeWallet: async (params: { partyId: string }) => Promise.resolve({}), listWallets: async (params: { - filter?: { networkIds?: string[]; signingProviderIds?: string[] } + filter?: { signingProviderIds?: string[] } }) => { - return await store.getAllWallets(params.filter) + return await store.getWallets(params.filter) }, sign: async ({ preparedTransaction, @@ -776,18 +782,17 @@ export const userController = ( }) const status = await networkStatus(ledgerClient) notifier.emit('statusChanged', { - kernel: { - ...kernelInfo, - userUrl: `${userUrl}/login/`, + provider: provider, + connection: { + isConnected: status.isConnected, + reason: status.reason ? status.reason : 'OK', + isNetworkConnected: status.isConnected, + networkReason: status.reason ? status.reason : 'OK', }, - isConnected: true, - isNetworkConnected: status.isConnected, - networkReason: status.reason ? status.reason : 'OK', network: { networkId: network.id, - ledgerApi: { - baseUrl: network.ledgerApi.baseUrl, - }, + ledgerApi: network.ledgerApi.baseUrl, + accessToken: accessToken, }, session: { id: newSessionId, @@ -844,12 +849,17 @@ export const userController = ( await store.removeSession() notifier.emit('statusChanged', { - kernel: kernelInfo, - isConnected: false, - isNetworkConnected: false, - networkReason: 'removed session', + provider: provider, + connection: { + isConnected: false, + reason: 'disconnect', + isNetworkConnected: false, + networkReason: 'removed session', + }, + network: undefined, + session: undefined, userUrl: `${userUrl}/login/`, - } as StatusEvent) + }) return null }, diff --git a/yarn.lock b/yarn.lock index 381179b79..ee0c735d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1426,10 +1426,57 @@ __metadata: languageName: unknown linkType: soft +"@canton-network/core-asyncapi-client@workspace:^, @canton-network/core-asyncapi-client@workspace:core/asyncapi-client": + version: 0.0.0-use.local + resolution: "@canton-network/core-asyncapi-client@workspace:core/asyncapi-client" + dependencies: + "@canton-network/core-ledger-client-types": "workspace:^" + "@canton-network/core-types": "workspace:^" + "@canton-network/core-wallet-auth": "workspace:^" + "@jest/globals": "npm:^30.2.0" + "@swc/core": "npm:^1.15.10" + "@swc/jest": "npm:^0.2.39" + "@types/jest": "npm:^30.0.0" + "@types/node": "npm:^25.0.10" + bignumber.js: "npm:^9.3.1" + jest: "npm:^30.2.0" + openapi-typescript: "npm:^7.10.1" + pino: "npm:^10.2.1" + ts-jest: "npm:^29.4.6" + ts-jest-resolver: "npm:^2.0.1" + tsup: "npm:^8.5.1" + typescript: "npm:^5.9.3" + languageName: unknown + linkType: soft + +"@canton-network/core-ledger-client-types@workspace:^, @canton-network/core-ledger-client-types@workspace:core/ledger-client-types": + version: 0.0.0-use.local + resolution: "@canton-network/core-ledger-client-types@workspace:core/ledger-client-types" + dependencies: + "@canton-network/core-types": "workspace:^" + "@jest/globals": "npm:^30.2.0" + "@swc/core": "npm:^1.15.10" + "@swc/jest": "npm:^0.2.39" + "@types/jest": "npm:^30.0.0" + "@types/node": "npm:^25.0.10" + bignumber.js: "npm:^9.3.1" + dayjs: "npm:^1.11.19" + jest: "npm:^30.2.0" + openapi-fetch: "npm:^0.15.0" + openapi-typescript: "npm:^7.10.1" + pino: "npm:^10.2.1" + ts-jest: "npm:^29.4.6" + ts-jest-resolver: "npm:^2.0.1" + tsup: "npm:^8.5.1" + typescript: "npm:^5.9.3" + languageName: unknown + linkType: soft + "@canton-network/core-ledger-client@workspace:^, @canton-network/core-ledger-client@workspace:core/ledger-client": version: 0.0.0-use.local resolution: "@canton-network/core-ledger-client@workspace:core/ledger-client" dependencies: + "@canton-network/core-ledger-client-types": "workspace:^" "@canton-network/core-ledger-proto": "workspace:^" "@canton-network/core-splice-client": "workspace:^" "@canton-network/core-token-standard": "workspace:^" @@ -2129,7 +2176,9 @@ __metadata: version: 0.0.0-use.local resolution: "@canton-network/wallet-sdk@workspace:sdk/wallet-sdk" dependencies: + "@canton-network/core-asyncapi-client": "workspace:^" "@canton-network/core-ledger-client": "workspace:^" + "@canton-network/core-ledger-client-types": "workspace:^" "@canton-network/core-ledger-proto": "workspace:^" "@canton-network/core-signing-lib": "workspace:^" "@canton-network/core-splice-client": "workspace:^" @@ -2446,11 +2495,11 @@ __metadata: linkType: soft "@daml.js/daml-stdlib-DA-NonEmpty-Types-1.0.0@file:../daml-stdlib-DA-NonEmpty-Types-1.0.0::locator=%40daml.js%2Fdaml-stdlib-DA-Validation-Types-1.0.0%40workspace%3Adamljs%2Ftoken-standard-models%2Fdaml-stdlib-DA-Validation-Types-1.0.0": - version: 3.3.0-snapshot.20250603.0 - resolution: "@daml.js/daml-stdlib-DA-NonEmpty-Types-1.0.0@file:../daml-stdlib-DA-NonEmpty-Types-1.0.0#../daml-stdlib-DA-NonEmpty-Types-1.0.0::hash=e228ad&locator=%40daml.js%2Fdaml-stdlib-DA-Validation-Types-1.0.0%40workspace%3Adamljs%2Ftoken-standard-models%2Fdaml-stdlib-DA-Validation-Types-1.0.0" + version: 0.0.0 + resolution: "@daml.js/daml-stdlib-DA-NonEmpty-Types-1.0.0@file:../daml-stdlib-DA-NonEmpty-Types-1.0.0#../daml-stdlib-DA-NonEmpty-Types-1.0.0::hash=0e2878&locator=%40daml.js%2Fdaml-stdlib-DA-Validation-Types-1.0.0%40workspace%3Adamljs%2Ftoken-standard-models%2Fdaml-stdlib-DA-Validation-Types-1.0.0" dependencies: "@mojotech/json-type-validation": "npm:^3.1.0" - checksum: 10c0/70832804e00c22bafddc61fe78393f3d8b913d3049e86974a2867dd3203b92d2c0fd5406e935159eefe9cd8700323066005294bae8b44f2e5efe1377a4ad92fa + checksum: 10c0/5ec3212e808b698fcc97cf8f5ef223f71507e1f37822b381f5353804ac4c4a432339974cd932543df08b1b6573d9a2724ff88b9eab923731f3bfd2669da935f2 languageName: node linkType: hard @@ -2495,11 +2544,11 @@ __metadata: linkType: soft "@daml.js/daml-stdlib-DA-Time-Types-1.0.0@file:../daml-stdlib-DA-Time-Types-1.0.0::locator=%40daml.js%2Ftoken-standard-models-1.0.0%40workspace%3Adamljs%2Ftoken-standard-models%2Ftoken-standard-models-1.0.0": - version: 3.3.0-snapshot.20250603.0 - resolution: "@daml.js/daml-stdlib-DA-Time-Types-1.0.0@file:../daml-stdlib-DA-Time-Types-1.0.0#../daml-stdlib-DA-Time-Types-1.0.0::hash=b18027&locator=%40daml.js%2Ftoken-standard-models-1.0.0%40workspace%3Adamljs%2Ftoken-standard-models%2Ftoken-standard-models-1.0.0" + version: 0.0.0 + resolution: "@daml.js/daml-stdlib-DA-Time-Types-1.0.0@file:../daml-stdlib-DA-Time-Types-1.0.0#../daml-stdlib-DA-Time-Types-1.0.0::hash=22072f&locator=%40daml.js%2Ftoken-standard-models-1.0.0%40workspace%3Adamljs%2Ftoken-standard-models%2Ftoken-standard-models-1.0.0" dependencies: "@mojotech/json-type-validation": "npm:^3.1.0" - checksum: 10c0/37954ae3ea035396517d5b430dc22f3c586f3c89451e5255aae6b6749cf7312adb41838df5cf0d1b0971c2ad4066d07fc7f7cd1e7ea1258aff9a197ff7e3c70a + checksum: 10c0/b9eb91452e776de9fcbd0f0bfd81b499953f9eb515ecf50a66f0073baea68ecbd4c96e96653a9de3e7e3f26c39039f7af84f097c77cf3622516fbbbd30119f65 languageName: node linkType: hard @@ -2521,11 +2570,11 @@ __metadata: linkType: soft "@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0@file:../ghc-stdlib-DA-Internal-Template-1.0.0::locator=%40daml.js%2Ftoken-standard-models-1.0.0%40workspace%3Adamljs%2Ftoken-standard-models%2Ftoken-standard-models-1.0.0": - version: 3.3.0-snapshot.20250603.0 - resolution: "@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0@file:../ghc-stdlib-DA-Internal-Template-1.0.0#../ghc-stdlib-DA-Internal-Template-1.0.0::hash=ec37e7&locator=%40daml.js%2Ftoken-standard-models-1.0.0%40workspace%3Adamljs%2Ftoken-standard-models%2Ftoken-standard-models-1.0.0" + version: 0.0.0 + resolution: "@daml.js/ghc-stdlib-DA-Internal-Template-1.0.0@file:../ghc-stdlib-DA-Internal-Template-1.0.0#../ghc-stdlib-DA-Internal-Template-1.0.0::hash=0340c7&locator=%40daml.js%2Ftoken-standard-models-1.0.0%40workspace%3Adamljs%2Ftoken-standard-models%2Ftoken-standard-models-1.0.0" dependencies: "@mojotech/json-type-validation": "npm:^3.1.0" - checksum: 10c0/f4b9f18936186607a4de048664bf1127df8ba9c5cbc5c8aa6e44292a46ecaea139a04b12e6cfa0596c3b6ef9d9d2707403d19554bf61de0a92c28f425f72504c + checksum: 10c0/5b8293bd19de7b3367bb5642d2273f947122be36be6974636f60388b0a117709833451bfe50be12caf3b071d8eb5d1e2b07a9a5ea24457085a080070facbacad languageName: node linkType: hard