create-canton-app 1.5.2 โ†’ 2.0.0

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.
package/README.md CHANGED
@@ -24,8 +24,8 @@ npx create-canton-app
24
24
 
25
25
  ```bash
26
26
  cd my-first-dapp
27
- daml build
28
- daml test
27
+ dpm build
28
+ dpm test
29
29
  ```
30
30
 
31
31
  **That's it!** You now have a working Canton smart contract.
@@ -60,30 +60,29 @@ Edit `src/commands/create.js` line 43:
60
60
 
61
61
  ```javascript
62
62
  choices: [
63
- { name: 'Bond Trading', value: 'bondtrading' },
63
+ { name: 'Token Transfer System Template', value: 'TokenTransfer' },
64
64
 
65
- { name: 'Collateral Master', value: 'collateral' },
65
+ { name: 'Multi-Party Agreement System Template', value: 'Multiparty' },
66
66
 
67
- { name: 'My Template', value: 'my-template' }, // ADD THIS
67
+ { name: 'Asset Holding System Template', value: 'AssetOwner' }
68
68
 
69
- { name: '๐Ÿ“„ Empty Template', value: 'empty' }
69
+ { name: 'My Template', value: 'my-template' }, // ADD THIS
70
70
  ]
71
71
  ```
72
72
 
73
73
  4. Try it
74
74
 
75
75
  ```bash
76
- daml build
77
- daml test
76
+ dpm build
77
+ dpm test
78
78
  ```
79
79
 
80
80
  ## Template Checklist
81
81
 
82
- - [ ] Compiles with `daml build`
83
- - [ ] Tests pass with `daml test`
82
+ - [ ] Compiles with `dpm build`
83
+ - [ ] Tests pass with `dpm test`
84
84
  - [ ] Includes inline comments
85
85
  - [ ] Has clear use case
86
- - [ ] daml.yaml includes `daml-script` dependency
87
86
 
88
87
  <div align="center">
89
88
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-canton-app",
3
- "version": "1.5.2",
3
+ "version": "2.0.0",
4
4
  "description": "Scaffold Canton Network/Daml projects in seconds",
5
5
  "main": "bin/create-canton-app.js",
6
6
  "repository": {
@@ -14,13 +14,13 @@ const colors = {
14
14
  bold: (text) => `\x1b[1m${text}\x1b[0m`
15
15
  };
16
16
 
17
- function isDamlInstalled() {
18
- return shell.which('daml') !== null;
17
+ function isDpmInstalled() {
18
+ return shell.which('dpm') !== null;
19
19
  }
20
20
 
21
- function getDamlVersion() {
21
+ function getDpmVersion() {
22
22
  try {
23
- const result = shell.exec('daml version', { silent: true });
23
+ const result = shell.exec('dpm version --active', { silent: true });
24
24
  const match = result.stdout.match(/(\d+\.\d+\.\d+)/);
25
25
  return match ? match[1] : null;
26
26
  } catch {
@@ -28,92 +28,161 @@ function getDamlVersion() {
28
28
  }
29
29
  }
30
30
 
31
- async function installDamlSDK() {
31
+ function getDpmTemplates() {
32
+ try {
33
+ const result = shell.exec('dpm new --list', { silent: true });
34
+ if (result.code !== 0) return [];
35
+
36
+ const lines = result.stdout.split('\n');
37
+ const templates = [];
38
+ let inTemplateList = false;
39
+
40
+ for (const line of lines) {
41
+ if (line.includes('following templates are available')) {
42
+ inTemplateList = true;
43
+ continue;
44
+ }
45
+ if (inTemplateList && line.trim()) {
46
+ const templateName = line.trim();
47
+ if (templateName && !templateName.startsWith('The')) {
48
+ templates.push(templateName);
49
+ }
50
+ }
51
+ }
52
+
53
+ return templates;
54
+ } catch {
55
+ return [];
56
+ }
57
+ }
58
+
59
+ async function installDpm() {
32
60
  console.log('');
33
- console.log(colors.yellow('โš ๏ธ Daml SDK not found!'));
61
+ console.log(colors.yellow('โš ๏ธ DPM (Digital Asset Package Manager) not found!'));
34
62
  console.log('');
35
- console.log(colors.white('Daml SDK is required to compile Canton smart contracts.'));
63
+ console.log(colors.white('DPM is the official Canton development tool.'));
64
+ console.log(colors.dim('(Replaces the deprecated Daml Assistant)'));
36
65
  console.log('');
37
66
 
38
67
  const answers = await inquirer.prompt([
39
68
  {
40
69
  type: 'confirm',
41
- name: 'installDaml',
42
- message: 'Would you like to install Daml SDK now? (Recommended)',
70
+ name: 'installDpm',
71
+ message: 'Would you like to install DPM now? (Recommended)',
43
72
  default: true
44
73
  }
45
74
  ]);
46
75
 
47
- if (!answers.installDaml) {
76
+ if (!answers.installDpm) {
48
77
  console.log('');
49
- console.log(colors.yellow('โš ๏ธ Skipping Daml SDK installation.'));
50
- console.log(colors.dim('You can install it later with:'));
51
- console.log(colors.white(' curl -sSL https://get.daml.com/ | sh'));
78
+ console.log(colors.yellow('โš ๏ธ Skipping DPM installation.'));
79
+ console.log(colors.dim('Install manually:'));
80
+ console.log(colors.white(' curl https://get.digitalasset.com/install/install.sh | sh'));
52
81
  console.log('');
53
82
  return false;
54
83
  }
55
84
 
56
85
  console.log('');
57
- const spinner = ora('Installing Daml SDK (this may take a few minutes)...').start();
86
+ const spinner = ora('Installing DPM (this may take a few minutes)...').start();
58
87
 
59
88
  try {
60
- const result = shell.exec('curl -sSL https://get.daml.com/ | sh', { silent: true });
89
+ // FIXED: Use correct installation URL
90
+ const result = shell.exec('curl -sSL https://get.digitalasset.com/install/install.sh | sh', {
91
+ silent: false // Show output so user can see progress
92
+ });
61
93
 
62
94
  if (result.code !== 0) {
63
- spinner.fail(colors.red('Failed to install Daml SDK'));
95
+ spinner.fail(colors.red('Failed to install DPM'));
64
96
  console.log('');
65
- console.log(colors.yellow('Please install manually:'));
66
- console.log(colors.white(' curl -sSL https://get.daml.com/ | sh'));
97
+ console.log(colors.yellow('Install manually:'));
98
+ console.log(colors.white(' curl https://get.digitalasset.com/install/install.sh | sh'));
67
99
  console.log('');
68
100
  return false;
69
101
  }
70
102
 
71
- const damlPath = path.join(process.env.HOME, '.daml', 'bin');
72
- process.env.PATH = `${damlPath}:${process.env.PATH}`;
103
+ // Add to PATH for current session
104
+ const dpmPath = path.join(process.env.HOME, '.dpm', 'bin');
105
+ process.env.PATH = `${dpmPath}:${process.env.PATH}`;
73
106
 
74
- spinner.succeed(colors.green('โœจ Daml SDK installed successfully!'));
107
+ spinner.succeed(colors.green('โœจ DPM installed successfully!'));
75
108
 
76
109
  console.log('');
77
- console.log(colors.cyan('๐Ÿ“ Important: Add Daml to your PATH permanently'));
110
+ console.log(colors.cyan('Important: Add DPM to your PATH permanently'));
78
111
  console.log(colors.dim('Add this line to your ~/.zshrc or ~/.bashrc:'));
79
112
  console.log('');
80
- console.log(colors.white(` export PATH="$HOME/.daml/bin:$PATH"`));
113
+ console.log(colors.white(` export PATH="$HOME/.dpm/bin:$PATH"`));
114
+ console.log('');
115
+ console.log(colors.yellow('Then reload your shell:'));
116
+ console.log(colors.white(' source ~/.zshrc'));
81
117
  console.log('');
82
118
 
83
119
  return true;
84
120
  } catch (error) {
85
121
  spinner.fail(colors.red('Installation failed: ' + error.message));
122
+ console.log('');
123
+ console.log(colors.yellow('Try installing manually:'));
124
+ console.log(colors.white(' curl https://get.digitalasset.com/install/install.sh | sh'));
125
+ console.log('');
126
+ return false;
127
+ }
128
+ }
129
+
130
+ async function createFromDpmTemplate(projectName, dpmTemplate) {
131
+ console.log('');
132
+ const spinner = ora(`Creating project from DPM template: ${dpmTemplate}...`).start();
133
+
134
+ try {
135
+ // CORRECT DPM syntax: dpm new --template <template-name> <project-name>
136
+ const result = shell.exec(`dpm new --template ${dpmTemplate} ${projectName}`, {
137
+ silent: false
138
+ });
139
+
140
+ if (result.code !== 0) {
141
+ spinner.fail(colors.red('Failed to create project'));
142
+ return false;
143
+ }
144
+
145
+ spinner.succeed(colors.green('Project created successfully!'));
146
+ return true;
147
+ } catch (error) {
148
+ spinner.fail(colors.red('Error: ' + error.message));
86
149
  return false;
87
150
  }
88
151
  }
89
152
 
90
153
  async function create(projectName, options) {
91
154
  try {
92
- // Check prerequisites
93
155
  console.log('');
94
156
  console.log(colors.cyan('๐Ÿ” Checking prerequisites...'));
95
157
  console.log('');
96
158
 
97
- if (!isDamlInstalled()) {
98
- const installed = await installDamlSDK();
99
- if (!installed) {
100
- console.log(colors.yellow('โš ๏ธ Continuing without Daml SDK...'));
159
+ let dpmJustInstalled = false;
160
+
161
+ if (!isDpmInstalled()) {
162
+ const installed = await installDpm();
163
+ if (installed) {
164
+ dpmJustInstalled = true;
165
+ // Give the system a moment to update PATH
166
+ await new Promise(resolve => setTimeout(resolve, 1000));
167
+ } else {
168
+ console.log(colors.yellow('โš ๏ธ Continuing without DPM...'));
169
+ console.log(colors.dim('You can install it later and use DPM templates.'));
101
170
  console.log('');
102
171
  }
103
172
  } else {
104
- const version = getDamlVersion();
105
- console.log(colors.green(`โœ… Daml SDK found${version ? ` (v${version})` : ''}`));
173
+ const version = getDpmVersion();
174
+ console.log(colors.green(`โœ… DPM found${version ? ` (v${version})` : ''}`));
106
175
  }
107
176
 
108
177
  if (!shell.which('java')) {
109
178
  console.log(colors.yellow('โš ๏ธ Java not found (optional, needed for tests)'));
179
+ console.log(colors.dim(' Install: brew install openjdk@17'));
110
180
  } else {
111
181
  console.log(colors.green('โœ… Java Runtime found'));
112
182
  }
113
183
 
114
184
  console.log('');
115
185
 
116
- // Get project name
117
186
  if (!projectName) {
118
187
  const answers = await inquirer.prompt([
119
188
  {
@@ -126,22 +195,97 @@ async function create(projectName, options) {
126
195
  projectName = answers.projectName;
127
196
  }
128
197
 
129
- // FIXED: Always ask for template if not explicitly provided via CLI flag
130
- let template = options.template;
131
-
132
- // Check if template was explicitly provided (not just the default)
198
+ let templateType;
133
199
  const wasTemplateProvided = process.argv.includes('--template') || process.argv.includes('-t');
134
200
 
201
+ // Check if DPM is available NOW (after potential installation)
202
+ const dpmAvailable = isDpmInstalled();
203
+
204
+ if (!wasTemplateProvided) {
205
+ const choices = [
206
+ { name: 'Beginner Templates (curated)', value: 'beginner' }
207
+ ];
208
+
209
+ // Only show DPM option if DPM is actually installed
210
+ if (dpmAvailable) {
211
+ choices.push({ name: 'Official DPM Templates (advanced)', value: 'dpm' });
212
+ }
213
+
214
+ const typeAnswers = await inquirer.prompt([
215
+ {
216
+ type: 'list',
217
+ name: 'templateType',
218
+ message: 'What type of template would you like?',
219
+ choices
220
+ }
221
+ ]);
222
+ templateType = typeAnswers.templateType;
223
+ } else {
224
+ templateType = 'beginner';
225
+ }
226
+
227
+ if (templateType === 'dpm') {
228
+ if (!dpmAvailable) {
229
+ console.log(colors.red('โŒ DPM required for official templates.'));
230
+ console.log(colors.yellow('Please install DPM first:'));
231
+ console.log(colors.white(' curl https://get.digitalasset.com/install/install.sh | sh'));
232
+ process.exit(1);
233
+ }
234
+
235
+ console.log('');
236
+ console.log(colors.cyan('Fetching DPM templates...'));
237
+
238
+ const dpmTemplates = getDpmTemplates();
239
+
240
+ if (dpmTemplates.length === 0) {
241
+ console.log(colors.yellow('โš ๏ธ Could not fetch DPM templates.'));
242
+ console.log(colors.dim('Try running: dpm new --list'));
243
+ console.log('');
244
+ console.log(colors.yellow('Falling back to beginner templates...'));
245
+ templateType = 'beginner';
246
+ } else {
247
+ console.log(colors.green(`โœ… Found ${dpmTemplates.length} DPM templates`));
248
+ console.log('');
249
+
250
+ const templateAnswers = await inquirer.prompt([
251
+ {
252
+ type: 'list',
253
+ name: 'dpmTemplate',
254
+ message: 'Select a DPM template:',
255
+ choices: dpmTemplates.map(t => ({ name: ` ${t}`, value: t })),
256
+ pageSize: 15
257
+ }
258
+ ]);
259
+
260
+ const success = await createFromDpmTemplate(projectName, templateAnswers.dpmTemplate);
261
+
262
+ if (success) {
263
+ console.log('');
264
+ console.log(colors.cyan(colors.bold('๐Ÿ“š Next steps:')));
265
+ console.log('');
266
+ console.log(colors.white(` cd ${projectName}`));
267
+ console.log(colors.white(` dpm build`));
268
+ console.log(colors.white(` dpm test`));
269
+ console.log('');
270
+ }
271
+
272
+ return;
273
+ }
274
+ }
275
+
276
+ // Handle beginner templates
277
+ let template = options.template;
278
+
135
279
  if (!wasTemplateProvided) {
136
280
  const answers = await inquirer.prompt([
137
281
  {
138
282
  type: 'list',
139
283
  name: 'template',
140
- message: 'Which template would you like to use?',
284
+ message: 'Which template would you like?',
141
285
  choices: [
142
- { name: 'Token Transfer System Template', value: 'TokenTransfer' },
143
- { name: 'Multi-Party Agreement System Template', value: 'Multiparty' },
144
- { name: 'Asset Holding System Template', value: 'AssetOwner' }
286
+ { name: 'Token Transfer System', value: 'TokenTransfer' },
287
+ { name: 'Multi-Party Agreement', value: 'Multiparty' },
288
+ { name: 'Asset Holding System', value: 'AssetOwner' }
145
289
  ]
146
290
  }
147
291
  ]);
@@ -164,7 +308,7 @@ async function create(projectName, options) {
164
308
  if (fs.existsSync(templatePath)) {
165
309
  fs.copySync(templatePath, projectPath);
166
310
  } else {
167
- spinner.warn(colors.yellow(`Template ${template} not found, creating empty structure...`));
311
+ spinner.warn(colors.yellow(`Template ${template} not found.`));
168
312
  fs.mkdirSync(path.join(projectPath, 'daml'), { recursive: true });
169
313
  }
170
314
 
@@ -179,24 +323,34 @@ async function create(projectName, options) {
179
323
  spinner.succeed(colors.green('โœจ Project created successfully!'));
180
324
 
181
325
  console.log('');
182
- console.log(colors.cyan(colors.bold('๐Ÿ“š Next steps:')));
326
+ console.log(colors.cyan(colors.bold('Next steps:')));
183
327
  console.log('');
184
328
  console.log(colors.white(` cd ${projectName}`));
185
329
 
186
- if (isDamlInstalled()) {
187
- console.log(colors.white(` daml build ${colors.dim('# Compile your contracts')}`));
188
- console.log(colors.white(` daml test ${colors.dim('# Run tests')}`));
330
+ if (dpmAvailable) {
331
+ console.log(colors.white(` dpm build ${colors.dim('# Compile')}`));
332
+ console.log(colors.white(` dpm test ${colors.dim('# Run tests')}`));
189
333
  } else {
190
- console.log(colors.yellow(` # First, install Daml SDK:`));
191
- console.log(colors.white(` curl -sSL https://get.daml.com/ | sh`));
334
+ console.log(colors.yellow(` # First, install DPM:`));
335
+ console.log(colors.white(` curl https://get.digitalasset.com/install/install.sh | sh`));
336
+ console.log(colors.white(` source ~/.zshrc`));
337
+ console.log(colors.white(` dpm build`));
192
338
  }
193
339
 
194
340
  console.log('');
195
- console.log(colors.dim('๐Ÿ“– Read README.md for more information'));
341
+ console.log(colors.dim('๐Ÿ“– Read README.md for more'));
196
342
  console.log('');
197
343
 
344
+ if (dpmJustInstalled) {
345
+ console.log(colors.cyan('๐Ÿ’ก Tip: Restart your terminal or run:'));
346
+ console.log(colors.white(` source ~/.zshrc`));
347
+ console.log(colors.dim('to use dpm commands immediately'));
348
+ console.log('');
349
+ }
350
+
198
351
  } catch (error) {
199
- console.error(colors.red('โŒ Error creating project:'), error.message);
352
+ console.error(colors.red('โŒ Error:'), error.message);
353
+ console.error(error.stack);
200
354
  process.exit(1);
201
355
  }
202
356
  }
@@ -204,13 +358,13 @@ async function create(projectName, options) {
204
358
  function createScripts(projectPath) {
205
359
  const compileScript = `#!/bin/bash
206
360
  echo "๐Ÿ”จ Compiling Daml contracts..."
207
- daml build
361
+ dpm build
208
362
  `;
209
363
  fs.writeFileSync(path.join(projectPath, 'scripts/compile.sh'), compileScript);
210
364
 
211
365
  const testScript = `#!/bin/bash
212
366
  echo "๐Ÿงช Running tests..."
213
- daml test
367
+ dpm test
214
368
  `;
215
369
  fs.writeFileSync(path.join(projectPath, 'scripts/test.sh'), testScript);
216
370
 
@@ -234,6 +388,7 @@ dependencies:
234
388
 
235
389
  function createGitignore(projectPath) {
236
390
  const gitignore = `.daml/
391
+ .dpm/
237
392
  *.dar
238
393
  *.log
239
394
  node_modules/
@@ -245,28 +400,31 @@ node_modules/
245
400
  function createReadme(projectPath, projectName, template) {
246
401
  const readme = `# ${projectName}
247
402
 
248
- > A Canton Network dApp built with create-canton-app
403
+ > Built with create-canton-app
249
404
 
250
405
  ## Template: ${template}
251
406
 
252
407
  ## Quick Start
253
408
 
254
409
  \`\`\`bash
255
- # Compile contracts
256
- daml build
410
+ dpm build # Compile
411
+ dpm test # Run tests
412
+ \`\`\`
413
+
414
+ ## Prerequisites
257
415
 
258
- # Run tests
259
- daml test
416
+ \`\`\`bash
417
+ curl https://get.digitalasset.com/install/install.sh | sh
260
418
  \`\`\`
261
419
 
262
420
  ## Learn More
263
421
 
264
422
  - [Canton Docs](https://docs.digitalasset.com)
265
- - [Daml Docs](https://docs.daml.com)
423
+ - [DPM Docs](https://docs.digitalasset.com/build/3.4/dpm/dpm.html)
266
424
  - [Canton Network](https://canton.network)
267
425
  `;
268
426
 
269
427
  fs.writeFileSync(path.join(projectPath, 'README.md'), readme);
270
428
  }
271
429
 
272
- module.exports = create;
430
+ module.exports = create;