Repository: o1-labs/zkapp-cli (js)

Issue:
Update "networks" in config.json to "deployAliases"
We've changed term for this from 'network' to 'deploy alias' for clarity, based on feedback from devs. But we still need to update this in the code.

- [ ] [Here](https://github.com/o1-labs/zkapp-cli/blob/main/templates/project-ts/config.json)
- [ ] needs changes in the deploy.js file to test for which property exists when reading from the file, so we can support both


Pull request:
Update "networks" in config.json to "deployAliases" 
Closes #217 

This PR updates `networks`  to `deployAliases` in the `config.json` and throughout the `zkApp-cli` for clarity. The `config.js` and `deploy.js` files were changed to support both cases if either `networks` or `deployAliases` are found in the `config.json`.  

Patch:
diff --git a/src/lib/config.js b/src/lib/config.js
index 6a6ef3e..254589d 100644
--- a/src/lib/config.js
+++ b/src/lib/config.js
@@ -9,8 +9,8 @@ const Client = require('mina-signer');
 const log = console.log;
 
 /**
- * Show existing networks in `config.json` and allow a user to add a new
- * network and url--and generate a key pair for it.
+ * Show existing deploy aliases in `config.json` and allow a user to add a new
+ * deploy alias and url--and generate a key pair for it.
  * @returns {Promise<void>}
  */
 async function config() {
@@ -32,29 +32,35 @@ async function config() {
     return;
   }
 
-  // Build table of existing networks found in their config.json
+  // Checks if developer has the legacy networks in config.json and renames it to deploy aliases.
+  if (Object.prototype.hasOwnProperty.call(config, 'networks')) {
+    Object.assign(config, { deployAliases: config.networks });
+    delete config.networks;
+  }
+
+  // Build table of existing deploy aliases found in their config.json
   let tableData = [[bold('Name'), bold('Url'), bold('Smart Contract')]];
-  for (const network in config.networks) {
-    const { url, smartContract } = config.networks[network];
+  for (const deployAliasName in config.deployAliases) {
+    const { url, smartContract } = config.deployAliases[deployAliasName];
     tableData.push([
-      network,
+      deployAliasName,
       url ?? '',
       smartContract ?? gray('(never deployed)'),
     ]);
   }
 
-  // Sort alphabetically by network name.
+  // Sort alphabetically by deploy alias name.
   tableData = tableData.sort((a, b) => a[0].localeCompare(b[0]));
 
   const tableConfig = {
     border: getBorderCharacters('norc'),
     header: {
       alignment: 'center',
-      content: bold('Networks in config.json'),
+      content: bold('Deploy aliases in config.json'),
     },
   };
 
-  // Show "none found", if no networks exist.
+  // Show "none found", if no deploy aliases exist.
   if (tableData.length === 1) {
     // Add some padding to empty name & url columns, to feel more natural.
     tableData[0][0] = tableData[0][0] + ' '.repeat(2);
@@ -68,10 +74,10 @@ async function config() {
   const msg = '\n  ' + table(tableData, tableConfig).replaceAll('\n', '\n  ');
   log(msg);
 
-  console.log('Add a new network:');
+  console.log('Add a new deploy alias:');
 
   // TODO: Later, show pre-configured list to choose from or let user
-  // add a custom network.
+  // add a custom deploy alias.
 
   function formatPrefixSymbol(state) {
     // Shows a cyan question mark when not submitted.
@@ -89,7 +95,7 @@ async function config() {
   const response = await prompt([
     {
       type: 'input',
-      name: 'network',
+      name: 'deployAliasName',
       message: (state) => {
         const style = state.submitted && !state.cancelled ? green : reset;
         return style('Choose a name (can be anything):');
@@ -98,7 +104,7 @@ async function config() {
       validate: async (val) => {
         val = val.toLowerCase().trim().replace(' ', '-');
         if (!val) return red('Name is required.');
-        if (Object.keys(config.networks).includes(val)) {
+        if (Object.keys(config.deployAliases).includes(val)) {
           return red('Name already exists.');
         }
         return true;
@@ -138,25 +144,33 @@ async function config() {
   ]);
 
   // If user presses "ctrl + c" during interactive prompt, exit.
-  const { network, url, fee } = response;
-  if (!network || !url || !fee) return;
+  const { deployAliasName, url, fee } = response;
+  if (!deployAliasName || !url || !fee) return;
 
   const keyPair = await step(
-    `Create key pair at keys/${network}.json`,
+    `Create key pair at keys/${deployAliasName}.json`,
     async () => {
       const client = new Client({ network: 'testnet' }); // TODO: Make this configurable for mainnet and testnet.
       let keyPair = client.genKeys();
-      fs.outputJsonSync(`${DIR}/keys/${network}.json`, keyPair, { spaces: 2 });
+      fs.outputJsonSync(`${DIR}/keys/${deployAliasName}.json`, keyPair, {
+        spaces: 2,
+      });
       return keyPair;
     }
   );
 
-  await step(`Add network to config.json`, async () => {
-    config.networks[network] = { url, keyPath: `keys/${network}.json`, fee };
+  await step(`Add deploy alias to config.json`, async () => {
+    config.deployAliases[deployAliasName] = {
+      url,
+      keyPath: `keys/${deployAliasName}.json`,
+      fee,
+    };
     fs.outputJsonSync(`${DIR}/config.json`, config, { spaces: 2 });
   });
 
-  const explorerName = getExplorerName(config?.networks[network]?.url);
+  const explorerName = getExplorerName(
+    config.deployAliases[deployAliasName]?.url
+  );
 
   const str =
     `\nSuccess!\n` +
@@ -164,7 +178,7 @@ async function config() {
     `\n  - If this is a testnet, request tMINA at:\n    https://faucet.minaprotocol.com/?address=${encodeURIComponent(
       keyPair.publicKey
     )}&?explorer=${explorerName}` +
-    `\n  - To deploy, run: \`zk deploy ${network}\``;
+    `\n  - To deploy, run: \`zk deploy ${deployAliasName}\``;
 
   log(green(str));
 }
diff --git a/src/lib/deploy.js b/src/lib/deploy.js
index c73713b..c151fcb 100644
--- a/src/lib/deploy.js
+++ b/src/lib/deploy.js
@@ -15,8 +15,8 @@ const log = console.log;
 const DEFAULT_GRAPHQL = 'https://proxy.berkeley.minaexplorer.com/graphql'; // The endpoint used to interact with the network
 
 /**
- * Deploy a smart contract to the specified network. If no network param is
- * provided, yargs will tell the user that the network param is required.
+ * Deploy a smart contract to the specified deploy alias. If no deploy alias param is
+ * provided, yargs will tell the user that the deploy alias param is required.
  * @param {string} alias   The deploy alias to deploy to.
  * @param {string} yes     Run non-interactively. I.e. skip confirmation steps.
  * @return {Promise<void>} Sends tx to a relayer, if confirmed by user.
@@ -43,6 +43,10 @@ async function deploy({ alias, yes }) {
   const latestCliVersion = await getLatestCliVersion();
   const installedCliVersion = await getInstalledCliVersion();
 
+  // Checks if developer has the legacy networks or deploy aliases in config.json
+  if (!Object.prototype.hasOwnProperty.call(config, 'deployAliases'))
+    config.deployAliases = config?.networks;
+
   if (hasBreakingChanges(installedCliVersion, latestCliVersion)) {
     log(red(`You are using an old zkapp-cli version ${installedCliVersion}.`));
     log(red(`The current version is ${latestCliVersion}.`));
@@ -51,7 +55,7 @@ async function deploy({ alias, yes }) {
   }
 
   if (!alias) {
-    const aliases = Object.keys(config?.networks);
+    const aliases = Object.keys(config?.deployAliases);
     if (!aliases.length) {
       log(red('No deploy aliases found in config.json.'));
       log(red('Run `zk config` to add a deploy alias, then try again.'));
@@ -83,14 +87,18 @@ async function deploy({ alias, yes }) {
 
   alias = alias.toLowerCase();
 
-  if (!config.networks[alias]) {
-    log(red('Network name not found in config.json.'));
-    log(red('You can add a network by running `zk config`.'));
+  if (!config.deployAliases[alias]) {
+    log(red('Deploy alias name not found in config.json.'));
+    log(red('You can add a deploy alias by running `zk config`.'));
     return;
   }
 
-  if (!config.networks[alias].url) {
-    log(red(`No 'url' property is specified for this network in config.json.`));
+  if (!config.deployAliases[alias].url) {
+    log(
+      red(
+        `No 'url' property is specified for this deploy alias in config.json.`
+      )
+    );
     log(red(`Please correct your config.json and try again.`));
     return;
   }
@@ -127,10 +135,10 @@ async function deploy({ alias, yes }) {
     return { smartContracts };
   });
 
-  // Identify which smart contract should be deployed for this network.
+  // Identify which smart contract should be deployed for this deploy alias.
   let contractName = chooseSmartContract(config, build, alias);
 
-  // If no smart contract is specified for this network in config.json &
+  // If no smart contract is specified for this deploy alias in config.json &
   // 2+ smart contracts exist in build.json, ask which they want to use.
   if (!contractName) {
     const res = await prompt({
@@ -159,9 +167,9 @@ async function deploy({ alias, yes }) {
     // the step formatting.
     await step('Choose smart contract', async () => {});
 
-    if (config.networks[alias]?.smartContract) {
+    if (config.deployAliases[alias]?.smartContract) {
       log(
-        `  The '${config.networks[alias]?.smartContract}' smart contract will be used\n  for this network as specified in config.json.`
+        `  The '${config.deployAliases[alias]?.smartContract}' smart contract will be used\n  for this deploy alias as specified in config.json.`
       );
     } else {
       log(
@@ -170,15 +178,15 @@ async function deploy({ alias, yes }) {
     }
   }
 
-  // Set the default smartContract name for this network in config.json.
-  // Occurs when this is the first time we're deploying to a given network.
+  // Set the default smartContract name for this deploy alias in config.json.
+  // Occurs when this is the first time we're deploying to a given deploy alias.
   // Important to ensure the same smart contract will always be deployed to
-  // the same network.
-  if (config.networks[alias]?.smartContract !== contractName) {
-    config.networks[alias].smartContract = contractName;
+  // the same deploy alias.
+  if (config.deployAliases[alias]?.smartContract !== contractName) {
+    config.deployAliases[alias].smartContract = contractName;
     fs.writeJSONSync(`${DIR}/config.json`, config, { spaces: 2 });
     log(
-      `  Your config.json was updated to always use this\n  smart contract when deploying to this network.`
+      `  Your config.json was updated to always use this\n  smart contract when deploying to this deploy alias.`
     );
   }
 
@@ -192,7 +200,7 @@ async function deploy({ alias, yes }) {
     snarkyjsImportPath
   );
 
-  const graphQLUrl = config?.networks[alias]?.url ?? DEFAULT_GRAPHQL;
+  const graphQLUrl = config.deployAliases[alias]?.url ?? DEFAULT_GRAPHQL;
 
   const { data: nodeStatus } = await sendGraphQL(
     graphQLUrl,
@@ -316,7 +324,7 @@ async function deploy({ alias, yes }) {
     log('  Using the cached verification key');
   }
 
-  let { fee } = config.networks[alias];
+  let { fee } = config.deployAliases[alias];
   if (!fee) {
     log(
       red(
@@ -375,8 +383,8 @@ async function deploy({ alias, yes }) {
   let transactionJson = transaction.json;
 
   const settings = [
-    [bold('Network'), reset(alias)],
-    [bold('Url'), reset(config.networks[alias].url)],
+    [bold('Deploy Alias'), reset(alias)],
+    [bold('Url'), reset(config.deployAliases[alias].url)],
     [bold('Smart Contract'), reset(contractName)],
   ];
 
@@ -549,15 +557,16 @@ async function findSmartContracts(path) {
 }
 
 /**
- * Choose which smart contract should be deployed for this network.
+ * Choose which smart contract should be deployed for this deploy alias.
  * @param {object} config  The config.json in object format.
  * @param {object} deploy  The build/build.json in object format.
+ * @param {string} deployAliasName The deploy alias name.
  * @returns {string}       The smart contract name.
  */
-function chooseSmartContract(config, deploy, network) {
-  // If the network in config.json has a smartContract specified, use it.
-  if (config.networks[network]?.smartContract) {
-    return config.networks[network]?.smartContract;
+function chooseSmartContract(config, deploy, deployAliasName) {
+  // If the deploy alias in config.json has a smartContract specified, use it.
+  if (config.deployAliases[deployAliasName]?.smartContract) {
+    return config.deployAliases[deployAliasName]?.smartContract;
   }
 
   // If only one smart contract exists in the build, use it.
@@ -566,7 +575,7 @@ function chooseSmartContract(config, deploy, network) {
   }
 
   // If 2+ smartContract classes exist in build.json, return falsy.
-  // We'll need to ask the user which they want to use for this network.
+  // We'll need to ask the user which they want to use for this deploy alias.
   return '';
 }
 
diff --git a/templates/project-ts/config.json b/templates/project-ts/config.json
index a6ba768..73c34d1 100644
--- a/templates/project-ts/config.json
+++ b/templates/project-ts/config.json
@@ -1,4 +1,4 @@
 {
   "version": 1,
-  "networks": {}
+  "deployAliases": {}
 }


Test patch:
diff --git a/src/lib/deploy.test.js b/src/lib/deploy.test.js
index 90cc99d..5ea1d45 100644
--- a/src/lib/deploy.test.js
+++ b/src/lib/deploy.test.js
@@ -9,32 +9,34 @@ describe('deploy.js', () => {
       it('should select that smart contract', () => {
         const config = {
           version: 1,
-          networks: {
+          deployAliases: {
             mainnet: {
               smartContract: 'Foo',
             },
           },
         };
         const deploy = {};
-        const network = 'mainnet';
-        const result = chooseSmartContract(config, deploy, network);
+        const deployAliasName = 'mainnet';
+
+        const result = chooseSmartContract(config, deploy, deployAliasName);
         expect(result).toEqual('Foo');
       });
     });
     describe('if the network in config.json does NOT have a smartContract specified', () => {
       const config = {
         version: 1,
-        networks: {
+        deployAliases: {
           mainnet: {},
         },
       };
-      const network = 'mainnet';
+
+      const deployAliasName = 'mainnet';
       describe('if only one smart contract exists in the build (deploy.json)', () => {
         it('should select that smart contract', () => {
           const deploy = {
             smartContracts: ['Bar'],
           };
-          const result = chooseSmartContract(config, deploy, network);
+          const result = chooseSmartContract(config, deploy, deployAliasName);
           expect(result).toEqual('Bar');
         });
       });
@@ -43,7 +45,8 @@ describe('deploy.js', () => {
           const deploy = {
             smartContracts: ['Foo', 'Bar'],
           };
-          const result = chooseSmartContract(config, deploy, network);
+          const deployAliasName = 'mainnet';
+          const result = chooseSmartContract(config, deploy, deployAliasName);
           expect(result).toEqual(''); // falsy
         });
       });