Просмотр исходного кода

ts, cli: Overrideable workspace program addresses (#308)

Armani Ferrante 4 лет назад
Родитель
Сommit
78d773a6de
4 измененных файлов с 64 добавлено и 33 удалено
  1. 25 28
      cli/src/main.rs
  2. 2 1
      ts/package.json
  3. 32 4
      ts/src/workspace.ts
  4. 5 0
      ts/yarn.lock

+ 25 - 28
cli/src/main.rs

@@ -952,10 +952,9 @@ fn test(
         // Bootup validator, if needed.
         let validator_handle = match cfg.provider.cluster.url() {
             "http://127.0.0.1:8899" => {
-                match skip_build {
-                    true => None,
-                    false => Some(build(None, false)?),
-                };
+                if !skip_build {
+                    build(None, false)?;
+                }
                 let flags = match skip_deploy {
                     true => None,
                     false => Some(genesis_flags(cfg)?),
@@ -1181,8 +1180,6 @@ fn start_test_validator(cfg: &Config, flags: Option<Vec<String>>) -> Result<Chil
     Ok(validator_handle)
 }
 
-// TODO: Testing and deploys should use separate sections of metadata.
-//       Similarly, each network should have separate metadata.
 fn deploy(
     url: Option<String>,
     keypair: Option<String>,
@@ -1326,28 +1323,6 @@ fn launch(
     })
 }
 
-// with_workspace ensures the current working directory is always the top level
-// workspace directory, i.e., where the `Anchor.toml` file is located, before
-// and after the closure invocation.
-//
-// The closure passed into this function must never change the working directory
-// to be outside the workspace. Doing so will have undefined behavior.
-fn with_workspace<R>(f: impl FnOnce(&Config, PathBuf, Option<PathBuf>) -> R) -> R {
-    set_workspace_dir_or_exit();
-
-    clear_program_keys().unwrap();
-
-    let (cfg, cfg_path, cargo_toml) = Config::discover()
-        .expect("Previously set the workspace dir")
-        .expect("Anchor.toml must always exist");
-    let r = f(&cfg, cfg_path, cargo_toml);
-
-    set_workspace_dir_or_exit();
-    clear_program_keys().unwrap();
-
-    r
-}
-
 // The Solana CLI doesn't redeploy a program if this file exists.
 // So remove it to make all commands explicit.
 fn clear_program_keys() -> Result<()> {
@@ -1652,3 +1627,25 @@ fn shell(cluster: Option<String>, wallet: Option<String>) -> Result<()> {
         Ok(())
     })
 }
+
+// with_workspace ensures the current working directory is always the top level
+// workspace directory, i.e., where the `Anchor.toml` file is located, before
+// and after the closure invocation.
+//
+// The closure passed into this function must never change the working directory
+// to be outside the workspace. Doing so will have undefined behavior.
+fn with_workspace<R>(f: impl FnOnce(&Config, PathBuf, Option<PathBuf>) -> R) -> R {
+    set_workspace_dir_or_exit();
+
+    clear_program_keys().unwrap();
+
+    let (cfg, cfg_path, cargo_toml) = Config::discover()
+        .expect("Previously set the workspace dir")
+        .expect("Anchor.toml must always exist");
+    let r = f(&cfg, cfg_path, cargo_toml);
+
+    set_workspace_dir_or_exit();
+    clear_program_keys().unwrap();
+
+    r
+}

+ 2 - 1
ts/package.json

@@ -33,7 +33,8 @@
     "find": "^0.3.0",
     "js-sha256": "^0.9.0",
     "pako": "^2.0.3",
-    "snake-case": "^3.0.4"
+    "snake-case": "^3.0.4",
+    "toml": "^3.0.0"
   },
   "devDependencies": {
     "@commitlint/cli": "^11.0.0",

+ 32 - 4
ts/src/workspace.ts

@@ -1,6 +1,8 @@
 import camelCase from "camelcase";
+import * as toml from "toml";
 import { PublicKey } from "@solana/web3.js";
 import { Program } from "./program";
+import { getProvider } from "./";
 
 let _populatedWorkspace = false;
 
@@ -44,13 +46,24 @@ const workspace = new Proxy({} as any, {
           const idlStr = fs.readFileSync(path);
           const idl = JSON.parse(idlStr);
           const name = camelCase(idl.name, { pascalCase: true });
-          programs[name] = new Program(
-            idl,
-            new PublicKey(idl.metadata.address)
-          );
+          if (idl.metadata && idl.metadata.address) {
+            programs[name] = new Program(
+              idl,
+              new PublicKey(idl.metadata.address)
+            );
+          }
           return programs;
         }, workspaceCache);
 
+      // Override the workspace programs if the user put them in the config.
+      const anchorToml = toml.parse(
+        fs.readFileSync(path.join(projectRoot, "Anchor.toml"), "utf-8")
+      );
+      const clusterId = anchorToml.provider.cluster;
+      if (anchorToml.clusters && anchorToml.clusters[clusterId]) {
+        attachWorkspaceOverride(workspaceCache, anchorToml.clusters[clusterId]);
+      }
+
       _populatedWorkspace = true;
     }
 
@@ -58,4 +71,19 @@ const workspace = new Proxy({} as any, {
   },
 });
 
+function attachWorkspaceOverride(
+  workspaceCache: { [key: string]: Program },
+  overrideConfig: { [key: string]: string }
+) {
+  Object.keys(overrideConfig).forEach((programName) => {
+    const wsProgramName = camelCase(programName, { pascalCase: true });
+    const oldProgram = workspaceCache[wsProgramName];
+    const overrideAddress = new PublicKey(overrideConfig[programName]);
+    workspaceCache[wsProgramName] = new Program(
+      oldProgram.idl,
+      overrideAddress
+    );
+  });
+}
+
 export default workspace;

+ 5 - 0
ts/yarn.lock

@@ -5112,6 +5112,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
     regex-not "^1.0.2"
     safe-regex "^1.1.0"
 
+toml@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee"
+  integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==
+
 tough-cookie@^2.3.3, tough-cookie@~2.5.0:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"