anchor/ts/src/workspace.ts

97 lines
2.8 KiB
TypeScript
Raw Normal View History

2021-01-02 22:40:17 -08:00
import camelCase from "camelcase";
import * as toml from "toml";
2021-01-04 23:59:52 -08:00
import { PublicKey } from "@solana/web3.js";
import { Program } from "./program";
import { Idl } from "./idl";
2021-01-02 22:40:17 -08:00
let _populatedWorkspace = false;
2021-05-10 13:12:20 -07:00
/**
* The `workspace` namespace provides a convenience API to automatically
* search for and deserialize [[Program]] objects defined by compiled IDLs
* in an Anchor workspace.
*
* This API is for Node only.
*/
const workspace = new Proxy({} as any, {
2021-01-04 23:59:52 -08:00
get(workspaceCache: { [key: string]: Program }, programName: string) {
const find = require("find");
const fs = require("fs");
const process = require("process");
if (typeof window !== "undefined") {
// Workspaces aren't available in the browser, yet.
return undefined;
2021-01-04 23:59:52 -08:00
}
if (!_populatedWorkspace) {
const path = require("path");
let projectRoot = process.cwd();
while (!fs.existsSync(path.join(projectRoot, "Anchor.toml"))) {
const parentDir = path.dirname(projectRoot);
if (parentDir === projectRoot) {
projectRoot = undefined;
}
projectRoot = parentDir;
}
if (projectRoot === undefined) {
throw new Error("Could not find workspace root.");
2021-01-02 22:40:17 -08:00
}
const idlMap = new Map<string, Idl>();
2021-01-04 23:59:52 -08:00
find
.fileSync(/target\/idl\/.*\.json/, projectRoot)
.reduce((programs: any, path: string) => {
const idlStr = fs.readFileSync(path);
const idl = JSON.parse(idlStr);
idlMap.set(idl.name, idl);
2021-01-04 23:59:52 -08:00
const name = camelCase(idl.name, { pascalCase: true });
if (idl.metadata && idl.metadata.address) {
programs[name] = new Program(
idl,
new PublicKey(idl.metadata.address)
);
}
2021-01-04 23:59:52 -08:00
return programs;
}, workspaceCache);
2021-01-02 22:40:17 -08:00
// 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],
idlMap
);
}
2021-01-04 23:59:52 -08:00
_populatedWorkspace = true;
}
2021-01-02 22:40:17 -08:00
2021-01-04 23:59:52 -08:00
return workspaceCache[programName];
},
});
2021-05-10 13:12:20 -07:00
function attachWorkspaceOverride(
workspaceCache: { [key: string]: Program },
overrideConfig: { [key: string]: string },
idlMap: Map<string, Idl>
) {
Object.keys(overrideConfig).forEach((programName) => {
const wsProgramName = camelCase(programName, { pascalCase: true });
const overrideAddress = new PublicKey(overrideConfig[programName]);
workspaceCache[wsProgramName] = new Program(
idlMap.get(programName),
overrideAddress
);
});
}
2021-05-10 13:12:20 -07:00
export default workspace;