Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
9208bff
Merge branch 'main' into wiktor/multisync-example
jarekr-da May 21, 2026
bf258a1
Merge branch 'main' into wiktor/multisync-example
jarekr-da May 21, 2026
c77528d
fix(example-15): use URL type for registryUrl
jarekr-da May 21, 2026
9eeb3c5
fix(ci): disable multi-sync for snippets tests
jarekr-da May 21, 2026
51db02f
fix(portfolio-e2e): wait for window.canton after page navigation
jarekr-da May 21, 2026
a4ec492
Merge branch 'main' into wiktor/multisync-example
jarekr-da May 21, 2026
99ecc1a
fix: build fix
jarekr-da May 21, 2026
949d160
Code Review: added wrapping function for registering party on multipl…
Viktor-Kalashnykov-da May 26, 2026
3f0d98b
Code Review: replaced usage of additional vetDar() function usage to …
Viktor-Kalashnykov-da May 26, 2026
1acb599
Code Review: added dependency to @canton-network/core-token-standard …
Viktor-Kalashnykov-da May 26, 2026
266a027
Code Review: simlified Amulet Minting
Viktor-Kalashnykov-da May 26, 2026
5aaa743
Code Review: Moved Amulet Template ID to Amulet Core Service
Viktor-Kalashnykov-da May 26, 2026
b658408
Code Review: removed condition checking for Bob token reassigning to …
Viktor-Kalashnykov-da May 26, 2026
0324a64
Code Review: moved functionality of connected synchronizers checking …
Viktor-Kalashnykov-da May 26, 2026
590cbb0
Code Review: moved constants from example 15 / _config.to to config.t…
Viktor-Kalashnykov-da May 26, 2026
1b18776
Code Review: added Codegen usage for DAML types usage in example 15
Viktor-Kalashnykov-da May 27, 2026
0828460
Code Review: extended party.create() method
Viktor-Kalashnykov-da May 27, 2026
e0d4658
Code Review: refactoring
Viktor-Kalashnykov-da May 27, 2026
298d493
Code Review: error handling for SUBMITTER_ALWAYS_STAKEHOLDER issue th…
Viktor-Kalashnykov-da May 27, 2026
fbfa773
Code Review: refactoring
Viktor-Kalashnykov-da May 28, 2026
2544ac3
Improvement: added multi-sync tests for CI
Viktor-Kalashnykov-da May 28, 2026
b5bcf4e
Merge branch 'main' into wiktor/multisync-example
Viktor-Kalashnykov-da May 28, 2026
db937f6
Fixex wallet-remote-gateway build
Viktor-Kalashnykov-da May 28, 2026
8c767fc
Fix for CI
Viktor-Kalashnykov-da May 28, 2026
f1f47b0
Merge branch 'main' into wiktor/multisync-example
Viktor-Kalashnykov-da May 28, 2026
ef06df8
Fix: post merge-conflitc resolution fix
Viktor-Kalashnykov-da May 28, 2026
02bb542
Fix: fixed location of DAR file assumption for multi-sync example
Viktor-Kalashnykov-da May 28, 2026
2630049
Test: testing failure of Multi-Sync tests
Viktor-Kalashnykov-da May 28, 2026
33b407e
Fix: added reassignment of Bob's Tokens to global sync again
Viktor-Kalashnykov-da May 28, 2026
a293498
Improvement: Removed unnecessary reassignments
Viktor-Kalashnykov-da May 28, 2026
be2e11e
Improvement: Compensation logic for errors during settlement
Viktor-Kalashnykov-da May 28, 2026
fff4dd6
Improvement: splitted _trade_ops.ts + imporved competing logic for Tr…
Viktor-Kalashnykov-da May 28, 2026
b5f1a3b
Code Review: fixed comment for vertPackage() function from SDK
Viktor-Kalashnykov-da May 28, 2026
0d08ac1
Improvement: removed vetAllPackages parameter from vetPackage() and r…
Viktor-Kalashnykov-da May 28, 2026
9c7d2ea
Refactoring: replaced trading app core project with DARs from localnet
Viktor-Kalashnykov-da Jun 2, 2026
687a8ce
feat: extended readme
jarekr-da Jun 2, 2026
a0a6aa8
fix: changed dar name
jarekr-da Jun 8, 2026
4e534d7
fix: use of disclosed contract
jarekr-da Jun 8, 2026
0901820
fix: pass disclosed token allocation to settle call site
jarekr-da Jun 8, 2026
66e10f5
Merge branch 'main' into wiktor/multisync-example
jarekr-da Jun 8, 2026
c657f73
Merge branch 'main' into wiktor/multisync-example
jarekr-da Jun 8, 2026
b6aac2f
feat: multi-sync example tests unification (#1912)
Viktor-Kalashnykov-da Jun 8, 2026
7ef18b0
feat: used multi-sync
jarekr-da Jun 8, 2026
64b4d9a
Merge branch 'main' into wiktor/multisync-example
jarekr-da Jun 8, 2026
1eeede0
feat: trying damls simplification
jarekr-da Jun 8, 2026
933d527
feat: filtering trade proposals
jarekr-da Jun 8, 2026
e542e4c
fix: removed redundant change
jarekr-da Jun 8, 2026
40c3409
fix: removed redundant change
jarekr-da Jun 8, 2026
2f72a00
fix: removed redundant change
jarekr-da Jun 8, 2026
ea5626e
tech: added todo
jarekr-da Jun 9, 2026
637a4c3
fix: eliminate custom multi-synchronizer bootstrap script (#1955)
mziolekda Jun 9, 2026
3db4194
fix(docs-wallet-integration-guide-examples): poll and reassign Alice'…
jarekr-da Jun 10, 2026
aabfd00
Merge branch 'main' into wiktor/multisync-example
jarekr-da Jun 10, 2026
9a349e7
feat: extended readme
jarekr-da Jun 10, 2026
c461f0d
ci: remove outdated multi-sync TODO comment from stress-tests workflow
jarekr-da Jun 10, 2026
3b7c631
docs(docs-wallet-integration-guide-examples): drop redundant --multi-…
jarekr-da Jun 10, 2026
78a5460
refactor(docs-wallet-integration-guide-examples): P3 does not know ab…
jarekr-da Jun 10, 2026
a57c5f2
refactor: participant names changed
jarekr-da Jun 11, 2026
2c9e97f
fix: TokenRules must be on sv
jarekr-da Jun 11, 2026
643d8b9
Merge branch 'main' into wiktor/multisync-example
jarekr-da Jun 11, 2026
9fb240f
feat: token standard off-ledger api for multisync example (#1974)
jarekr-da Jun 11, 2026
ed3683e
doc: improved run-15 documentation
jarekr-da Jun 11, 2026
c8c487a
refactor(wallet-sdk): remove synchronizer auto-selection; callers pro…
jarekr-da Jun 9, 2026
2cb939b
test(docs-wallet-integration-guide-examples): pass synchronizerId in …
jarekr-da Jun 9, 2026
62235d8
fix(core-wallet-test-utils): pass global synchronizerId to DAR upload…
jarekr-da Jun 10, 2026
4c72ddc
fix(docs-wallet-integration-guide-examples): pass global synchronizer…
jarekr-da Jun 10, 2026
97092ae
fix(docs-wallet-integration-guide-examples): pass global synchronizer…
jarekr-da Jun 10, 2026
51c5d16
fix(docs-wallet-integration-guide-examples): pass synchronizerId to p…
jarekr-da Jun 10, 2026
b0ebe21
Improvement: unified retrieval of Global Synchronizer inside SDK
Viktor-Kalashnykov-da Jun 11, 2026
ebf92df
Improvement: caching of synchronizers in SDK
Viktor-Kalashnykov-da Jun 11, 2026
6fae77c
Improvement: refactoring
Viktor-Kalashnykov-da Jun 11, 2026
0256183
refactor(wallet-sdk): generalize cached synchronizer resolution by alias
jarekr-da Jun 15, 2026
e1a29a5
refactor: extract multi-sync example logic into core modules + test i…
jarekr-da Jun 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/actions/setup_localnet/artifacts/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ inputs:
splice_version:
description: 'Splice version (required)'
required: true
multi_sync:
description: 'Enable multi-sync profile (default: true)'
required: false
default: 'true'
runs:
using: 'composite'
steps:
Expand All @@ -31,4 +35,4 @@ runs:

- name: Start Localnet
shell: bash
run: yarn start:localnet -- --network=${{ inputs.network }}
run: yarn start:localnet -- --network=${{ inputs.network }} ${{ inputs.multi_sync == 'false' && '--no-multi-sync' || '' }}
17 changes: 17 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ jobs:
with:
network: ${{ matrix.network }}
splice_version: ${{ matrix.network == 'devnet' && needs.version-config.outputs.devnet_splice_version || needs.version-config.outputs.mainnet_splice_version }}
multi_sync: 'true'

- name: Start remote WK
run: yarn pm2 start ecosystem.ci.config.js --env development
Expand Down Expand Up @@ -450,6 +451,7 @@ jobs:
with:
network: ${{ matrix.network }}
splice_version: ${{ matrix.network == 'devnet' && needs.version-config.outputs.devnet_splice_version || needs.version-config.outputs.mainnet_splice_version }}
multi_sync: 'true'

- uses: ./.github/actions/check_resources

Expand Down Expand Up @@ -500,6 +502,21 @@ jobs:
with:
network: ${{ matrix.network }}
splice_version: ${{ matrix.network == 'devnet' && needs.version-config.outputs.devnet_splice_version || needs.version-config.outputs.mainnet_splice_version }}
multi_sync: 'true'

- name: Restore DPM cache
uses: actions/cache/restore@v5
with:
path: |
~/.dpm
key: dpm-${{ runner.os }}-${{ needs.version-config.outputs.daml_release_version }}

- name: Generate featured DARs
run: yarn script:generate:featured-dars

- name: Rebuild DAML-dependent packages
run: |
yarn workspace @canton-network/core-test-token build

- uses: ./.github/actions/check_resources

Expand Down
1 change: 0 additions & 1 deletion .github/workflows/stress-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ jobs:
run: yarn script:test:stress-scripts

- uses: ./.github/actions/check_resources

- name: Stop localnet (${{ github.event.inputs.network || 'devnet' }})
if: always()
run: yarn stop:localnet -- --network=${{ github.event.inputs.network || 'devnet' }}
Expand Down
69 changes: 0 additions & 69 deletions canton/multi-sync/app-synchronizer.sc

This file was deleted.

55 changes: 55 additions & 0 deletions core/amulet-ops/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"name": "@canton-network/core-amulet-ops",
"version": "0.0.1",
"type": "module",
"description": "SDK-level Amulet operations (tap/mint, allocate) built on the wallet SDK",
"license": "Apache-2.0",
"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 --onSuccess \"tsc\"",
"dev": "tsup --watch --onSuccess \"tsc\"",
"clean": "tsc -b --clean; rm -rf dist",
"flatpack": "yarn pack --out \"$FLATPACK_OUTDIR\"",
"test": "vitest run --project node --passWithNoTests",
"test:coverage": "vitest run --project node --coverage --passWithNoTests"
},
"dependencies": {
"@canton-network/core-amulet-service": "workspace:^"
},
"peerDependencies": {
"@canton-network/core-signing-lib": "workspace:^",
"@canton-network/wallet-sdk": "workspace:^",
"pino": "^10.3.1"
},
"devDependencies": {
"@canton-network/core-signing-lib": "workspace:^",
"@canton-network/wallet-sdk": "workspace:^",
"@vitest/coverage-v8": "^4.1.2",
"pino": "^10.3.1",
"tsup": "^8.5.1",
"typescript": "^5.9.3",
"vitest": "^4.1.2"
},
"files": [
"dist/**"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/canton-network/wallet.git",
"directory": "core/amulet-ops"
}
}
95 changes: 95 additions & 0 deletions core/amulet-ops/src/allocation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import type { Logger } from 'pino'
import type { SDKInterface } from '@canton-network/wallet-sdk'
import { AMULET_TEMPLATE_ID } from '@canton-network/core-amulet-service'
import type { SigningParty } from './tap.js'

const AMULET_INSTRUMENT = {
id: 'Amulet',
displayName: 'Amulet',
symbol: 'CC',
} as const

export interface AllocateAmuletParams {
sdk: SDKInterface<'token'>
sender: SigningParty
adminPartyId: string
registryUrl: URL
globalSynchronizerId: string
logger?: Logger
}

/**
* Allocates the sender's Amulet holding against its leg of a pending token
* allocation request.
*
* Looks up the sender's transfer leg in the pending allocation request, reads its
* Amulet holding, builds the allocation instruction for the Amulet instrument, and
* submits it signed by the sender.
*
* @returns The transfer-leg id that was allocated.
*/
export async function allocateAmulet(
params: AllocateAmuletParams
): Promise<string> {
const {
sdk,
sender,
adminPartyId,
registryUrl,
globalSynchronizerId,
logger,
} = params
const token = sdk.token

const pendingRequests = await token.allocation.request.pending(
sender.partyId
)
const requestView = pendingRequests[0].interfaceViewValue!
const legId = Object.keys(requestView.transferLegs).find(
(key) => requestView.transferLegs[key].sender === sender.partyId
)!
if (!legId) throw new Error('No transfer leg found for sender')

const amuletHoldings = await sdk.ledger.acsReader.readJsContracts({
templateIds: [AMULET_TEMPLATE_ID],
parties: [sender.partyId],
filterByParty: true,
})
const amuletHoldingCid = amuletHoldings[0]?.contractId
if (!amuletHoldingCid)
throw new Error('Amulet holding not found for sender')

const [command, disclosedContracts] =
await token.allocation.instruction.create({
allocationSpecification: {
settlement: requestView.settlement,
transferLegId: legId,
transferLeg: requestView.transferLegs[legId],
},
asset: {
id: AMULET_INSTRUMENT.id,
displayName: AMULET_INSTRUMENT.displayName,
symbol: AMULET_INSTRUMENT.symbol,
registryUrl,
admin: adminPartyId,
},
inputUtxos: [amuletHoldingCid],
requestedAt: new Date().toISOString(),
})

await sdk.ledger
.prepare({
partyId: sender.partyId,
commands: [command],
disclosedContracts,
synchronizerId: globalSynchronizerId,
})
.sign(sender.privateKey)
.execute({ partyId: sender.partyId })

logger?.info('Amulet allocated for sender leg (global synchronizer)')
return legId
}
8 changes: 8 additions & 0 deletions core/amulet-ops/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

export { mintAmulet } from './tap.js'
export type { MintAmuletParams, SigningParty } from './tap.js'

export { allocateAmulet } from './allocation.js'
export type { AllocateAmuletParams } from './allocation.js'
46 changes: 46 additions & 0 deletions core/amulet-ops/src/tap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import type { Logger } from 'pino'
import type { PrivateKey } from '@canton-network/core-signing-lib'
import type { SDKInterface } from '@canton-network/wallet-sdk'

export interface SigningParty {
partyId: string
privateKey: PrivateKey
}

export interface MintAmuletParams {
sdk: SDKInterface<'amulet'>
receiver: SigningParty
amount: string
synchronizerId: string
logger?: Logger
}

/**
* Taps (mints) `amount` Amulet into `receiver`'s wallet on `synchronizerId`.
*
* Builds the tap command via the SDK's `amulet` namespace, then prepares, signs,
* and executes it as a single-party submission by the receiver.
*/
export async function mintAmulet(params: MintAmuletParams): Promise<void> {
const { sdk, receiver, amount, synchronizerId, logger } = params

const [tapCommand, disclosedContracts] = await sdk.amulet.tap(
receiver.partyId,
amount
)

await sdk.ledger
.prepare({
partyId: receiver.partyId,
commands: tapCommand,
disclosedContracts,
synchronizerId,
})
.sign(receiver.privateKey)
.execute({ partyId: receiver.partyId })

logger?.info(`Amulet minted (${amount}) for receiver on synchronizer`)
}
8 changes: 8 additions & 0 deletions core/amulet-ops/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.web.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
"include": ["src"]
}
11 changes: 11 additions & 0 deletions core/amulet-ops/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 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'],
platform: 'node',
})
29 changes: 29 additions & 0 deletions core/amulet-ops/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { defineConfig, defineProject } from 'vitest/config'

export default defineConfig({
test: {
coverage: {
include: ['src/**/*.ts'],
provider: 'v8',
reporter: ['text', 'html', 'lcov'],
thresholds: {
lines: 0,
functions: 0,
branches: 0,
statements: 0,
},
},
projects: [
defineProject({
test: {
name: 'node',
environment: 'node',
include: ['src/**/*.test.ts'],
},
}),
],
},
})
1 change: 1 addition & 0 deletions core/amulet-service/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2025-2026 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

export * from './interface-ids.const.js'
export * from './amulet-service.js'
Loading