@layerzerolabs/common-canton 0.2.114 → 0.2.116

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,252 +0,0 @@
1
- #!/usr/bin/env tsx
2
- /// <reference types="node" />
3
- /**
4
- * Captures disclosure flow using SecretBox contract.
5
- *
6
- * Scenario:
7
- * 1. Alice creates a SecretBox with Bob as the "opener"
8
- * 2. Bob is NOT an observer - he can't see the contract normally
9
- * 3. Alice creates disclosure and shares it with Bob
10
- * 4. Bob uses disclosure to exercise OpenBox choice (flexible controller)
11
- *
12
- * Usage:
13
- * tsx test/mocks/scripts/capture-disclosure.ts
14
- *
15
- * Output:
16
- * test/mocks/captured-disclosure.json
17
- */
18
-
19
- import type { ContractId } from '@daml/types';
20
- import * as path from 'path';
21
-
22
- import {
23
- MnemonicSignerAdapter,
24
- SignatureFormat,
25
- SignatureType,
26
- } from '@layerzerolabs/ver-signer-adapter';
27
- import { CantonClient } from '../../../src/client/index.js';
28
- // Import test contracts
29
- import { packageId as testPackageId } from '../../../src/daml/sdk-test-0.0.1/lib/index.js';
30
- import { SecretBox } from '../../../src/daml/sdk-test-0.0.1/lib/SdkTest/module.js';
31
- import { Configuration } from '../../../src/open-api/runtime.js';
32
- import { CantonSdk } from '../../../src/sdk/index.js';
33
- import type { ExternalSignature } from '../../../src/types.js';
34
- import {
35
- CANTON_URL,
36
- type CapturedInteraction,
37
- createCapturingFetch,
38
- createOperationContext,
39
- EXTERNAL_PARTY_DERIVATION_PATH,
40
- EXTERNAL_PARTY_ID,
41
- EXTERNAL_PARTY_JWT_TOKEN,
42
- EXTERNAL_PARTY_KEY_FINGERPRINT,
43
- EXTERNAL_PARTY_MNEMONIC,
44
- EXTERNAL_PARTY_USER_ID,
45
- INTERNAL_PARTY_ID,
46
- INTERNAL_PARTY_JWT_TOKEN,
47
- INTERNAL_PARTY_USER_ID,
48
- printEndpointSummary,
49
- saveInteractions,
50
- } from './capture-utils.js';
51
-
52
- // ─────────────────────────────────────────────────────────────────────────────
53
- // Signing Helper (for Bob - external party)
54
- // ─────────────────────────────────────────────────────────────────────────────
55
-
56
- async function signTransaction(hash: string, party: string): Promise<ExternalSignature> {
57
- const signer = new MnemonicSignerAdapter({
58
- mnemonicConfig: {
59
- getMnemonic: async () => ({
60
- mnemonic: EXTERNAL_PARTY_MNEMONIC,
61
- path: EXTERNAL_PARTY_DERIVATION_PATH,
62
- }),
63
- },
64
- });
65
- const hashBytes = Uint8Array.from(Buffer.from(hash, 'base64'));
66
- const { createHash } = await import('crypto');
67
- const messageHash = createHash('sha256').update(hashBytes).digest();
68
-
69
- const derSignature = await signer.sign({
70
- data: messageHash,
71
- signatureType: SignatureType.ECDSA,
72
- format: SignatureFormat.DER,
73
- });
74
-
75
- return {
76
- party,
77
- signature: Buffer.from(derSignature).toString('base64'),
78
- signedBy: EXTERNAL_PARTY_KEY_FINGERPRINT,
79
- format: 'SIGNATURE_FORMAT_DER',
80
- signingAlgorithmSpec: 'SIGNING_ALGORITHM_SPEC_EC_DSA_SHA_256',
81
- };
82
- }
83
-
84
- // ─────────────────────────────────────────────────────────────────────────────
85
- // Disclosure Flow
86
- // ─────────────────────────────────────────────────────────────────────────────
87
-
88
- async function captureDisclosureFlow(
89
- aliceSdk: CantonSdk,
90
- bobSdk: CantonSdk,
91
- setOperation: (name: string) => void,
92
- ): Promise<void> {
93
- // 1. Alice creates a SecretBox with Bob as opener
94
- // Bob is NOT an observer - he can't see this contract!
95
- setOperation('alice_create_secret_box');
96
- console.log('1. Alice creates SecretBox with Bob as opener...');
97
-
98
- const createCmd = aliceSdk.buildCreate(
99
- SecretBox as any,
100
- {
101
- owner: INTERNAL_PARTY_ID,
102
- opener: EXTERNAL_PARTY_ID, // Bob can open it...
103
- secret: 'test-secret-not-a-real-secret-just-testing',
104
- isOpen: false,
105
- },
106
- testPackageId,
107
- );
108
-
109
- const createResult = await aliceSdk.submit({ actAs: [INTERNAL_PARTY_ID] }, [createCmd]);
110
- const createWait = await aliceSdk.waitForCommand(createResult.commandId, {
111
- parties: [INTERNAL_PARTY_ID],
112
- beginExclusive: createResult.completionOffset,
113
- timeoutMs: 60_000,
114
- });
115
- if (createWait.status !== 'accepted') throw new Error(`Create failed: ${createWait.status}`);
116
-
117
- const createUpdate = await aliceSdk.fetchTransaction(createWait.updateId, [INTERNAL_PARTY_ID]);
118
- const createdEventWrapper = (createUpdate.events ?? []).find((e) => 'CreatedEvent' in e);
119
- if (!createdEventWrapper || !('CreatedEvent' in createdEventWrapper))
120
- throw new Error('No contract created');
121
-
122
- const secretBoxId = createdEventWrapper.CreatedEvent.contractId;
123
- console.log(` Created: ${secretBoxId.slice(0, 20)}...`);
124
- console.log(` Bob is opener but NOT observer - he needs disclosure!`);
125
-
126
- // 2. Alice creates disclosure of the SecretBox for Bob
127
- setOperation('alice_create_disclosure');
128
- console.log('2. Alice creates disclosure...');
129
-
130
- const disclosure = await aliceSdk.createDisclosure(
131
- secretBoxId as ContractId<typeof SecretBox>,
132
- [INTERNAL_PARTY_ID],
133
- );
134
- if (!disclosure) throw new Error('Failed to create disclosure');
135
-
136
- console.log(` Disclosure created`);
137
- console.log(` Template: ${disclosure.templateId}`);
138
- console.log(` Blob: ${disclosure.createdEventBlob.slice(0, 40)}...`);
139
-
140
- // 3. Bob exercises OpenBox WITH disclosure
141
- // Without disclosure, Bob can't see the contract and would get an error
142
- setOperation('bob_prepare_open_box');
143
- console.log('3. Bob exercises OpenBox with disclosure (signed)...');
144
-
145
- const exerciseCmd = bobSdk.buildExercise(
146
- SecretBox.OpenBox,
147
- secretBoxId as ContractId<typeof SecretBox>,
148
- {},
149
- testPackageId,
150
- );
151
-
152
- // Prepare with disclosure - Bob can now see Alice's SecretBox
153
- const prepared = await bobSdk.prepareForSigning(
154
- { actAs: [EXTERNAL_PARTY_ID] },
155
- [exerciseCmd],
156
- { disclosedContracts: [disclosure] }, // <-- Disclosure required!
157
- );
158
-
159
- setOperation('bob_submit_open_box');
160
- const signature = await signTransaction(prepared.preparedTransactionHash, EXTERNAL_PARTY_ID);
161
- const exerciseResult = await bobSdk.submitSigned(prepared, [signature]);
162
-
163
- setOperation('bob_wait_open_box');
164
- const exerciseWait = await bobSdk.waitForCommand(exerciseResult.commandId, {
165
- parties: [EXTERNAL_PARTY_ID],
166
- beginExclusive: exerciseResult.completionOffset,
167
- timeoutMs: 60_000,
168
- });
169
-
170
- if (exerciseWait.status !== 'accepted') {
171
- throw new Error(`OpenBox failed: ${JSON.stringify(exerciseWait)}`);
172
- }
173
-
174
- setOperation('bob_fetch_result');
175
- const exerciseUpdate = await bobSdk.fetchTransaction(exerciseWait.updateId, [
176
- EXTERNAL_PARTY_ID,
177
- ]);
178
- const openedBoxWrapper = (exerciseUpdate.events ?? []).find((e) => 'CreatedEvent' in e);
179
- const openedBox =
180
- openedBoxWrapper && 'CreatedEvent' in openedBoxWrapper
181
- ? openedBoxWrapper.CreatedEvent
182
- : null;
183
- console.log(` Box opened! New contract: ${openedBox?.contractId?.slice(0, 20)}...`);
184
-
185
- // 4. Verify the box is now open
186
- setOperation('alice_verify_opened');
187
- console.log('4. Alice verifies the box is open...');
188
-
189
- const verifyContract = await aliceSdk.get(
190
- openedBox!.contractId as ContractId<typeof SecretBox>,
191
- [INTERNAL_PARTY_ID],
192
- );
193
- const isOpen = (verifyContract?.payload as any)?.isOpen;
194
- console.log(` isOpen: ${isOpen}`);
195
-
196
- if (isOpen) {
197
- console.log(" ✓ Disclosure flow complete! Bob opened Alice's box.");
198
- } else {
199
- throw new Error('Box should be open!');
200
- }
201
- }
202
-
203
- // ─────────────────────────────────────────────────────────────────────────────
204
- // Main
205
- // ─────────────────────────────────────────────────────────────────────────────
206
-
207
- async function main() {
208
- console.log('Capturing disclosure flow: SecretBox\n');
209
- console.log('Scenario: Alice creates box, Bob is opener but NOT observer.');
210
- console.log('Bob needs disclosure to see and exercise the contract.\n');
211
-
212
- const captured: CapturedInteraction[] = [];
213
- const { setOperation, getOperation } = createOperationContext();
214
-
215
- // Alice (internal party) - owner of the SecretBox
216
- const aliceConfig = new Configuration({
217
- basePath: CANTON_URL,
218
- fetchApi: createCapturingFetch({ captured, getOperation }),
219
- headers: { Authorization: `Bearer ${INTERNAL_PARTY_JWT_TOKEN}` },
220
- });
221
- const aliceClient = new CantonClient(aliceConfig, INTERNAL_PARTY_USER_ID);
222
- const aliceSdk = new CantonSdk(aliceClient);
223
-
224
- // Bob (external party) - opener, needs disclosure
225
- const bobConfig = new Configuration({
226
- basePath: CANTON_URL,
227
- fetchApi: createCapturingFetch({ captured, getOperation }),
228
- headers: { Authorization: `Bearer ${EXTERNAL_PARTY_JWT_TOKEN}` },
229
- });
230
- const bobClient = new CantonClient(bobConfig, EXTERNAL_PARTY_USER_ID);
231
- const bobSdk = new CantonSdk(bobClient);
232
-
233
- await captureDisclosureFlow(aliceSdk, bobSdk, setOperation);
234
-
235
- const outputFile = path.join(import.meta.dirname, '..', 'captured-disclosure.json');
236
- saveInteractions(outputFile, captured);
237
- printEndpointSummary(captured);
238
- }
239
-
240
- main().catch(async (err) => {
241
- console.error('Error:', err.message);
242
- if (err.response && typeof err.response.text === 'function') {
243
- try {
244
- const body = await err.response.text();
245
- console.error('Response body:', body);
246
- } catch {
247
- /* ignore */
248
- }
249
- }
250
- console.error(err.stack);
251
- process.exit(1);
252
- });
@@ -1,184 +0,0 @@
1
- #!/usr/bin/env tsx
2
- /// <reference types="node" />
3
- /**
4
- * Captures real Canton API interactions for external party (signed submission) flow.
5
- *
6
- * Usage:
7
- * tsx test/mocks/scripts/capture-external-requests.ts
8
- *
9
- * Output:
10
- * test/mocks/captured-external-requests.json
11
- */
12
-
13
- import type { ContractId } from '@daml/types';
14
- import * as path from 'path';
15
-
16
- import {
17
- MnemonicSignerAdapter,
18
- SignatureFormat,
19
- SignatureType,
20
- } from '@layerzerolabs/ver-signer-adapter';
21
- import { CantonClient } from '../../../src/client/index.js';
22
- // Import SDK test contracts
23
- import { packageId } from '../../../src/daml/sdk-test-0.0.1/lib/index.js';
24
- import { SimpleAsset } from '../../../src/daml/sdk-test-0.0.1/lib/SdkTest/module.js';
25
- import { Configuration } from '../../../src/open-api/runtime.js';
26
- import { CantonSdk } from '../../../src/sdk/index.js';
27
- import type { ExternalSignature } from '../../../src/types.js';
28
- import {
29
- CANTON_URL,
30
- type CapturedInteraction,
31
- createCapturingFetch,
32
- createOperationContext,
33
- EXTERNAL_PARTY_DERIVATION_PATH,
34
- EXTERNAL_PARTY_ID,
35
- EXTERNAL_PARTY_JWT_TOKEN,
36
- EXTERNAL_PARTY_KEY_FINGERPRINT,
37
- EXTERNAL_PARTY_MNEMONIC,
38
- EXTERNAL_PARTY_USER_ID,
39
- printEndpointSummary,
40
- saveInteractions,
41
- } from './capture-utils.js';
42
-
43
- // ─────────────────────────────────────────────────────────────────────────────
44
- // Signing Helper
45
- // ─────────────────────────────────────────────────────────────────────────────
46
-
47
- async function signTransaction(hash: string, party: string): Promise<ExternalSignature> {
48
- const signer = new MnemonicSignerAdapter({
49
- mnemonicConfig: {
50
- getMnemonic: async () => ({
51
- mnemonic: EXTERNAL_PARTY_MNEMONIC,
52
- path: EXTERNAL_PARTY_DERIVATION_PATH,
53
- }),
54
- },
55
- });
56
- const hashBytes = Uint8Array.from(Buffer.from(hash, 'base64'));
57
- const { createHash } = await import('crypto');
58
- const messageHash = createHash('sha256').update(hashBytes).digest();
59
-
60
- const derSignature = await signer.sign({
61
- data: messageHash,
62
- signatureType: SignatureType.ECDSA,
63
- format: SignatureFormat.DER,
64
- });
65
-
66
- return {
67
- party,
68
- signature: Buffer.from(derSignature).toString('base64'),
69
- signedBy: EXTERNAL_PARTY_KEY_FINGERPRINT,
70
- format: 'SIGNATURE_FORMAT_DER',
71
- signingAlgorithmSpec: 'SIGNING_ALGORITHM_SPEC_EC_DSA_SHA_256',
72
- };
73
- }
74
-
75
- // ─────────────────────────────────────────────────────────────────────────────
76
- // Capture Flow
77
- // ─────────────────────────────────────────────────────────────────────────────
78
-
79
- async function captureExternalSigningFlow(
80
- sdk: CantonSdk,
81
- setOperation: (name: string) => void,
82
- ): Promise<void> {
83
- // 1. Prepare Create
84
- setOperation('external_prepare_create');
85
- const payload = {
86
- owner: EXTERNAL_PARTY_ID,
87
- value: '200',
88
- description: 'Test asset for external party flow',
89
- };
90
- const createCmd = sdk.buildCreate(SimpleAsset as any, payload, packageId);
91
- const preparedCreate = await sdk.prepareForSigning({ actAs: [EXTERNAL_PARTY_ID] }, [createCmd]);
92
-
93
- // 2. Submit Signed Create
94
- setOperation('external_submit_create');
95
- const createSignature = await signTransaction(
96
- preparedCreate.preparedTransactionHash,
97
- EXTERNAL_PARTY_ID,
98
- );
99
- const createResult = await sdk.submitSigned(preparedCreate, [createSignature]);
100
-
101
- // 3. Wait for Create
102
- setOperation('external_wait_create');
103
- const createCompletion = await sdk.waitForCommand(createResult.commandId, {
104
- parties: [EXTERNAL_PARTY_ID],
105
- beginExclusive: createResult.completionOffset,
106
- timeoutMs: 60_000,
107
- });
108
- if (createCompletion.status !== 'accepted') throw new Error('Create rejected');
109
-
110
- // 4. Fetch Contract ID
111
- setOperation('external_fetch_created_contract_id');
112
- const update = await sdk.fetchTransaction(createCompletion.updateId, [EXTERNAL_PARTY_ID]);
113
- const createdWrapper = (update.events ?? []).find((e) => 'CreatedEvent' in e);
114
- const contractId =
115
- createdWrapper && 'CreatedEvent' in createdWrapper
116
- ? createdWrapper.CreatedEvent.contractId
117
- : undefined;
118
- if (!contractId) throw new Error('No contract created');
119
-
120
- // 5. Query Contract
121
- setOperation('external_query_contract');
122
- await sdk.get(contractId as ContractId<typeof SimpleAsset>, [EXTERNAL_PARTY_ID]);
123
-
124
- // 6. Prepare Archive
125
- setOperation('external_prepare_archive');
126
- const archiveCmd = sdk.buildExercise(
127
- SimpleAsset.Archive,
128
- contractId as ContractId<typeof SimpleAsset>,
129
- {},
130
- packageId,
131
- );
132
- const preparedArchive = await sdk.prepareForSigning({ actAs: [EXTERNAL_PARTY_ID] }, [
133
- archiveCmd,
134
- ]);
135
-
136
- // 7. Submit Signed Archive
137
- setOperation('external_submit_archive');
138
- const archiveSignature = await signTransaction(
139
- preparedArchive.preparedTransactionHash,
140
- EXTERNAL_PARTY_ID,
141
- );
142
- const archiveResult = await sdk.submitSigned(preparedArchive, [archiveSignature]);
143
-
144
- // 8. Wait for Archive
145
- setOperation('external_wait_archive');
146
- await sdk.waitForCommand(archiveResult.commandId, {
147
- parties: [EXTERNAL_PARTY_ID],
148
- beginExclusive: archiveResult.completionOffset,
149
- timeoutMs: 60_000,
150
- });
151
-
152
- // 9. Verify Archived
153
- setOperation('external_verify_archived');
154
- await sdk.get(contractId as ContractId<typeof SimpleAsset>, [EXTERNAL_PARTY_ID]);
155
- }
156
-
157
- // ─────────────────────────────────────────────────────────────────────────────
158
- // Main
159
- // ─────────────────────────────────────────────────────────────────────────────
160
-
161
- async function main() {
162
- console.log('Capturing external party requests...');
163
-
164
- const captured: CapturedInteraction[] = [];
165
- const { setOperation, getOperation } = createOperationContext();
166
-
167
- const config = new Configuration({
168
- basePath: CANTON_URL,
169
- fetchApi: createCapturingFetch({ captured, getOperation }),
170
- headers: { Authorization: `Bearer ${EXTERNAL_PARTY_JWT_TOKEN}` },
171
- });
172
- const sdk = new CantonSdk(new CantonClient(config, EXTERNAL_PARTY_USER_ID));
173
-
174
- await captureExternalSigningFlow(sdk, setOperation);
175
-
176
- const outputFile = path.join(import.meta.dirname, '..', 'captured-external-requests.json');
177
- saveInteractions(outputFile, captured);
178
- printEndpointSummary(captured);
179
- }
180
-
181
- main().catch((err) => {
182
- console.error('Error:', err.message);
183
- process.exit(1);
184
- });
@@ -1,122 +0,0 @@
1
- #!/usr/bin/env tsx
2
- /// <reference types="node" />
3
- /**
4
- * Captures real Canton API interactions for internal party (normal submission) flow.
5
- *
6
- * Usage:
7
- * tsx test/mocks/scripts/capture-internal-requests.ts
8
- *
9
- * Output:
10
- * test/mocks/captured-internal-requests.json
11
- */
12
-
13
- import type { ContractId } from '@daml/types';
14
- import * as path from 'path';
15
-
16
- import { CantonClient } from '../../../src/client/index.js';
17
- // Import SDK test contracts
18
- import { packageId } from '../../../src/daml/sdk-test-0.0.1/lib/index.js';
19
- import { SimpleAsset } from '../../../src/daml/sdk-test-0.0.1/lib/SdkTest/module.js';
20
- import { Configuration } from '../../../src/open-api/runtime.js';
21
- import { CantonSdk } from '../../../src/sdk/index.js';
22
- import {
23
- CANTON_URL,
24
- type CapturedInteraction,
25
- createCapturingFetch,
26
- createOperationContext,
27
- INTERNAL_PARTY_ID,
28
- INTERNAL_PARTY_JWT_TOKEN,
29
- INTERNAL_PARTY_USER_ID,
30
- printEndpointSummary,
31
- saveInteractions,
32
- } from './capture-utils.js';
33
-
34
- // ─────────────────────────────────────────────────────────────────────────────
35
- // Capture Flow
36
- // ─────────────────────────────────────────────────────────────────────────────
37
-
38
- async function captureInternalPartyFlow(sdk: CantonSdk, setOperation: (name: string) => void) {
39
- // 1. Connected Synchronizers
40
- setOperation('list_synchronizers');
41
- await sdk.connectedSynchronizers();
42
-
43
- // 2. Create Contract
44
- setOperation('create_contract');
45
- const payload = {
46
- owner: INTERNAL_PARTY_ID,
47
- value: '100',
48
- description: 'Test asset for internal party flow',
49
- };
50
- const createCmd = sdk.buildCreate(SimpleAsset as any, payload, packageId);
51
- const submitResult = await sdk.submit({ actAs: [INTERNAL_PARTY_ID] }, [createCmd]);
52
-
53
- // 3. Wait for Create
54
- setOperation('wait_create');
55
- const waitResult = await sdk.waitForCommand(submitResult.commandId, {
56
- parties: [INTERNAL_PARTY_ID],
57
- beginExclusive: submitResult.completionOffset,
58
- timeoutMs: 60_000,
59
- });
60
- if (waitResult.status !== 'accepted') throw new Error('Create rejected');
61
-
62
- // 4. Fetch Contract ID
63
- setOperation('fetch_created_contract_id');
64
- const update = await sdk.fetchTransaction(waitResult.updateId, [INTERNAL_PARTY_ID]);
65
- const createdWrapper = (update.events ?? []).find((e) => 'CreatedEvent' in e);
66
- const contractId = (
67
- createdWrapper && 'CreatedEvent' in createdWrapper
68
- ? createdWrapper.CreatedEvent.contractId
69
- : undefined
70
- ) as ContractId<typeof SimpleAsset>;
71
- if (!contractId) throw new Error('No contract created');
72
-
73
- // 5. Query Contract
74
- setOperation('query_contract');
75
- await sdk.get(contractId, [INTERNAL_PARTY_ID]);
76
-
77
- // 6. Archive Contract
78
- setOperation('archive_contract');
79
- const archiveCmd = sdk.buildExercise(SimpleAsset.Archive, contractId, {}, packageId);
80
- const archiveResult = await sdk.submit({ actAs: [INTERNAL_PARTY_ID] }, [archiveCmd]);
81
-
82
- // 7. Wait for Archive
83
- setOperation('wait_archive');
84
- await sdk.waitForCommand(archiveResult.commandId, {
85
- parties: [INTERNAL_PARTY_ID],
86
- beginExclusive: archiveResult.completionOffset,
87
- timeoutMs: 60_000,
88
- });
89
-
90
- // 8. Verify Archived
91
- setOperation('verify_archived');
92
- await sdk.get(contractId, [INTERNAL_PARTY_ID]);
93
- }
94
-
95
- // ─────────────────────────────────────────────────────────────────────────────
96
- // Main
97
- // ─────────────────────────────────────────────────────────────────────────────
98
-
99
- async function main() {
100
- console.log('Capturing internal party requests...');
101
-
102
- const captured: CapturedInteraction[] = [];
103
- const { setOperation, getOperation } = createOperationContext();
104
-
105
- const config = new Configuration({
106
- basePath: CANTON_URL,
107
- fetchApi: createCapturingFetch({ captured, getOperation }),
108
- headers: { Authorization: `Bearer ${INTERNAL_PARTY_JWT_TOKEN}` },
109
- });
110
- const sdk = new CantonSdk(new CantonClient(config, INTERNAL_PARTY_USER_ID));
111
-
112
- await captureInternalPartyFlow(sdk, setOperation);
113
-
114
- const outputFile = path.join(import.meta.dirname, '..', 'captured-internal-requests.json');
115
- saveInteractions(outputFile, captured);
116
- printEndpointSummary(captured);
117
- }
118
-
119
- main().catch((err) => {
120
- console.error('Error:', err.message);
121
- process.exit(1);
122
- });