@lightprotocol/zk-compression-cli 0.3.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.
Files changed (106) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +189 -0
  3. package/accounts/address_merkle_tree_C83cpRN6oaafjNgMQJvaYgAz592EP5wunKvbokeTKPLn.json +1 -0
  4. package/accounts/address_merkle_tree_queue_HNjtNrjt6irUPYEgxhx2Vcs42koK9fxzm3aFLHVaaRWz.json +1 -0
  5. package/accounts/governance_authority_pda_3MtrKu5Mjgh3JqeE5PeRzw2Ld28XjFgbbph67E6UERSx.json +1 -0
  6. package/accounts/group_pda_Edo2YjXU5eE17CejPBkupPgFLcYuAX47pGZmM7s2hAkj.json +1 -0
  7. package/accounts/merkle_tree_pubkey_5bdFnXU47QjzGpzHfXnxcEi5WXyxzEAZzd1vrE39bf1W.json +1 -0
  8. package/accounts/nullifier_queue_pubkey_44J4oDXpjPAbzHCSc24q7NEiPekss4sAbLd8ka4gd9CZ.json +1 -0
  9. package/accounts/registered_program_pda_ytwwVWhQUMoTKdirKmvEW5xCRVr4B2dJZnToiHtE2L2.json +1 -0
  10. package/bin/account_compression.so +0 -0
  11. package/bin/light_compressed_pda.so +0 -0
  12. package/bin/light_compressed_token.so +0 -0
  13. package/bin/light_registry.so +0 -0
  14. package/bin/light_system_program.so +0 -0
  15. package/bin/prover-darwin-arm64 +0 -0
  16. package/bin/prover-darwin-x64 +0 -0
  17. package/bin/prover-linux-arm64 +0 -0
  18. package/bin/prover-linux-x64 +0 -0
  19. package/bin/prover-windows-arm64.exe +0 -0
  20. package/bin/prover-windows-x64.exe +0 -0
  21. package/bin/proving-keys/combined_26_1_1.key +0 -0
  22. package/bin/proving-keys/combined_26_1_1.vkey +1 -0
  23. package/bin/proving-keys/combined_26_1_2.key +0 -0
  24. package/bin/proving-keys/combined_26_1_2.vkey +1 -0
  25. package/bin/proving-keys/combined_26_2_1.key +0 -0
  26. package/bin/proving-keys/combined_26_2_1.vkey +1 -0
  27. package/bin/proving-keys/combined_26_2_2.key +0 -0
  28. package/bin/proving-keys/combined_26_2_2.vkey +1 -0
  29. package/bin/proving-keys/combined_26_3_1.key +0 -0
  30. package/bin/proving-keys/combined_26_3_1.vkey +1 -0
  31. package/bin/proving-keys/combined_26_3_2.key +0 -0
  32. package/bin/proving-keys/combined_26_3_2.vkey +1 -0
  33. package/bin/proving-keys/combined_26_4_1.key +0 -0
  34. package/bin/proving-keys/combined_26_4_1.vkey +1 -0
  35. package/bin/proving-keys/combined_26_4_2.key +0 -0
  36. package/bin/proving-keys/combined_26_4_2.vkey +1 -0
  37. package/bin/proving-keys/inclusion_26_1.key +0 -0
  38. package/bin/proving-keys/inclusion_26_1.vkey +1 -0
  39. package/bin/proving-keys/inclusion_26_2.key +0 -0
  40. package/bin/proving-keys/inclusion_26_2.vkey +1 -0
  41. package/bin/proving-keys/inclusion_26_3.key +0 -0
  42. package/bin/proving-keys/inclusion_26_3.vkey +1 -0
  43. package/bin/proving-keys/inclusion_26_4.key +0 -0
  44. package/bin/proving-keys/inclusion_26_4.vkey +1 -0
  45. package/bin/proving-keys/inclusion_26_8.key +0 -0
  46. package/bin/proving-keys/inclusion_26_8.vkey +1 -0
  47. package/bin/proving-keys/non-inclusion_26_1.key +0 -0
  48. package/bin/proving-keys/non-inclusion_26_1.vkey +1 -0
  49. package/bin/proving-keys/non-inclusion_26_2.key +0 -0
  50. package/bin/proving-keys/non-inclusion_26_2.vkey +1 -0
  51. package/bin/spl_noop.so +0 -0
  52. package/config.json +3 -0
  53. package/dist/commands/approve-and-mint-to/index.d.ts +14 -0
  54. package/dist/commands/approve-and-mint-to/index.js +64 -0
  55. package/dist/commands/balance/index.d.ts +12 -0
  56. package/dist/commands/balance/index.js +50 -0
  57. package/dist/commands/compress-sol/index.d.ts +12 -0
  58. package/dist/commands/compress-sol/index.js +48 -0
  59. package/dist/commands/compress-spl/index.d.ts +13 -0
  60. package/dist/commands/compress-spl/index.js +61 -0
  61. package/dist/commands/config/config.d.ts +11 -0
  62. package/dist/commands/config/config.js +69 -0
  63. package/dist/commands/config/index.d.ts +2 -0
  64. package/dist/commands/config/index.js +5 -0
  65. package/dist/commands/create-mint/index.d.ts +17 -0
  66. package/dist/commands/create-mint/index.js +67 -0
  67. package/dist/commands/decompress-sol/index.d.ts +12 -0
  68. package/dist/commands/decompress-sol/index.js +46 -0
  69. package/dist/commands/decompress-spl/index.d.ts +13 -0
  70. package/dist/commands/decompress-spl/index.js +60 -0
  71. package/dist/commands/mint-to/index.d.ts +14 -0
  72. package/dist/commands/mint-to/index.js +64 -0
  73. package/dist/commands/register-mint/index.d.ts +14 -0
  74. package/dist/commands/register-mint/index.js +50 -0
  75. package/dist/commands/start-prover/index.d.ts +11 -0
  76. package/dist/commands/start-prover/index.js +30 -0
  77. package/dist/commands/test-validator/index.d.ts +16 -0
  78. package/dist/commands/test-validator/index.js +61 -0
  79. package/dist/commands/transfer/index.d.ts +13 -0
  80. package/dist/commands/transfer/index.js +62 -0
  81. package/dist/index.d.ts +3 -0
  82. package/dist/index.js +8 -0
  83. package/dist/psp-utils/download.d.ts +34 -0
  84. package/dist/psp-utils/download.js +203 -0
  85. package/dist/psp-utils/index.d.ts +1 -0
  86. package/dist/psp-utils/index.js +4 -0
  87. package/dist/utils/constants.d.ts +14 -0
  88. package/dist/utils/constants.js +19 -0
  89. package/dist/utils/index.d.ts +5 -0
  90. package/dist/utils/index.js +8 -0
  91. package/dist/utils/initTestEnv.d.ts +38 -0
  92. package/dist/utils/initTestEnv.js +171 -0
  93. package/dist/utils/process.d.ts +30 -0
  94. package/dist/utils/process.js +162 -0
  95. package/dist/utils/processPhotonIndexer.d.ts +1 -0
  96. package/dist/utils/processPhotonIndexer.js +45 -0
  97. package/dist/utils/processProverServer.d.ts +3 -0
  98. package/dist/utils/processProverServer.js +49 -0
  99. package/dist/utils/standardFlags.d.ts +8 -0
  100. package/dist/utils/standardFlags.js +36 -0
  101. package/dist/utils/utils.d.ts +26 -0
  102. package/dist/utils/utils.js +150 -0
  103. package/oclif.manifest.json +684 -0
  104. package/package.json +122 -0
  105. package/test_bin/dev +17 -0
  106. package/test_bin/run +5 -0
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.downloadBinIfNotExists = exports.downloadFile = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const axios_1 = tslib_1.__importDefault(require("axios"));
6
+ const fs = tslib_1.__importStar(require("fs"));
7
+ const util_1 = require("util");
8
+ const cli_progress_1 = tslib_1.__importDefault(require("cli-progress"));
9
+ const path = tslib_1.__importStar(require("path"));
10
+ const tar = tslib_1.__importStar(require("tar"));
11
+ const zlib = tslib_1.__importStar(require("zlib"));
12
+ const stateless_js_1 = require("@lightprotocol/stateless.js");
13
+ const fileExists = (0, util_1.promisify)(fs.exists);
14
+ async function latestRelease(owner, repo) {
15
+ const github = "https://api.github.com";
16
+ console.log(`🔍 Checking the latest release of ${github}/repos/${owner}/${repo}/releases/latest`);
17
+ const response = await axios_1.default.get(`${github}/repos/${owner}/${repo}/releases/latest`);
18
+ const tag_name = response.data.tag_name;
19
+ console.log(`📦 The newest release of ${repo} is ${tag_name}`);
20
+ return response.data.tag_name;
21
+ }
22
+ /**
23
+ * Makes the given file executable.
24
+ * @param filePath - The path to the file to make executable.
25
+ */
26
+ function makeExecutable(filePath) {
27
+ fs.chmodSync(filePath, "755");
28
+ }
29
+ /**
30
+ * Makes all files without extensions in the given directory executable.
31
+ * @param dirPath - The path to the directory to make files executable.
32
+ * @returns {Promise<void>}
33
+ */
34
+ async function makeExecutableInDir(dirPath) {
35
+ const files = fs.readdirSync(dirPath);
36
+ for (const file of files) {
37
+ const filePath = path.join(dirPath, file);
38
+ const stat = fs.statSync(filePath);
39
+ const extname = path.extname(filePath);
40
+ if (stat.isDirectory()) {
41
+ await makeExecutableInDir(filePath);
42
+ }
43
+ else if (!filePath.startsWith(".") &&
44
+ (extname === "" || extname === ".sh")) {
45
+ fs.chmodSync(filePath, "755");
46
+ }
47
+ }
48
+ }
49
+ /**
50
+ * Decompresses the given downloaded data stream to the given local file path.
51
+ * @param decompressor - The decompressor to use.
52
+ * @param data - The data stream to decompress.
53
+ * @param localFilePath - The local file path to decompress the data to. If
54
+ * provided, that only file will be decompressed from the archive. If not
55
+ * provided, all files will be decompressed to `dirPath`.
56
+ * @param dirPath - The directory path to decompress the data to.
57
+ * @returns {Promise<void>}
58
+ */
59
+ function handleTarFile({ decompressor, data, localFilePath, dirPath, }) {
60
+ const parser = new tar.Parse();
61
+ data.pipe(decompressor).pipe(parser);
62
+ parser.on("entry", (entry) => {
63
+ const baseName = path.parse(entry.path).base;
64
+ const outputFilePath = localFilePath
65
+ ? localFilePath
66
+ : path.join(dirPath, entry.path);
67
+ if (baseName.startsWith("._")) {
68
+ // Ignore AppleDouble files.
69
+ entry.resume();
70
+ }
71
+ else if (!localFilePath ||
72
+ entry.path === path.parse(localFilePath).base) {
73
+ // Unpack the file if it's the one we want, or if we want all files.
74
+ // Create directory if it does not exist.
75
+ const dir = path.dirname(outputFilePath);
76
+ if (!fs.existsSync(dir)) {
77
+ fs.mkdirSync(dir, { recursive: true });
78
+ }
79
+ // Check if entry is a file before attempting to create a write stream for it
80
+ if (entry.type === "file") {
81
+ entry.pipe(fs.createWriteStream(outputFilePath));
82
+ }
83
+ else if (entry.type === "File") {
84
+ entry.pipe(fs.createWriteStream(outputFilePath));
85
+ }
86
+ else {
87
+ entry.resume();
88
+ }
89
+ }
90
+ else {
91
+ entry.resume();
92
+ }
93
+ });
94
+ return new Promise((resolve, _reject) => {
95
+ parser.on("end", () => {
96
+ // Make the file executable after it has been written.
97
+ if (localFilePath) {
98
+ makeExecutable(localFilePath);
99
+ }
100
+ else {
101
+ makeExecutableInDir(dirPath);
102
+ }
103
+ resolve();
104
+ });
105
+ });
106
+ }
107
+ /**
108
+ * Downloads a file from the given URL to the given local file path.
109
+ * @param localFilePath - The local file path to download the file to. If
110
+ * provided and the download file is an archive, only the file with the same
111
+ * name as `localFilePath` will be extracted from the archive. If not provided,
112
+ * all files will be extracted to `dirPath`.
113
+ * @param dirPath - The path to the directory where the file(s) will be created.
114
+ * @param url - The URL to download the file from.
115
+ * @returns {Promise<void>}
116
+ */
117
+ async function downloadFile({ localFilePath, dirPath, url, }) {
118
+ console.log(`📥 Downloading ${url}...`);
119
+ let retries = 3;
120
+ while (retries > 0) {
121
+ try {
122
+ const { data, headers } = await (0, axios_1.default)({
123
+ url,
124
+ method: "GET",
125
+ responseType: "stream",
126
+ });
127
+ const totalLength = headers["content-length"];
128
+ const progressBar = new cli_progress_1.default.SingleBar({}, cli_progress_1.default.Presets.shades_classic);
129
+ progressBar.start(totalLength, 0);
130
+ data.on("data", (chunk) => {
131
+ progressBar.increment(chunk.length);
132
+ });
133
+ data.on("end", () => {
134
+ progressBar.stop();
135
+ });
136
+ // If the file is a tar.gz file, decompress it while it's being written.
137
+ if (url.endsWith(".tar.gz")) {
138
+ console.log(`📦 Extracting ${url}...`);
139
+ const decompressor = zlib.createGunzip();
140
+ await handleTarFile({
141
+ decompressor,
142
+ data,
143
+ localFilePath,
144
+ dirPath,
145
+ });
146
+ }
147
+ else {
148
+ if (!localFilePath)
149
+ throw new Error("localFilePath is undefined");
150
+ const writeStream = fs.createWriteStream(localFilePath);
151
+ data.pipe(writeStream);
152
+ return new Promise((resolve, reject) => {
153
+ writeStream.on("finish", () => {
154
+ makeExecutable(localFilePath);
155
+ resolve();
156
+ });
157
+ writeStream.on("error", reject);
158
+ });
159
+ }
160
+ break;
161
+ }
162
+ catch (error) {
163
+ retries--;
164
+ console.error(`Failed to download ${url}. Retries left: ${retries}`);
165
+ if (retries <= 0) {
166
+ throw new Error(`Failed to download ${url} after multiple attempts.`);
167
+ }
168
+ await (0, stateless_js_1.sleep)(1000);
169
+ }
170
+ }
171
+ }
172
+ exports.downloadFile = downloadFile;
173
+ /**
174
+ * Download a binary from the given release artifact of the GitHub repository,
175
+ * if it was not already downloaded.
176
+ * @param localFilePath - The path to the local file (which either already
177
+ * exists or will be created).
178
+ * @param dirPath - The path to the directory where the file(s) will be created.
179
+ * @param owner - The owner of the GitHub repository.
180
+ * @param repoName - The name of the GitHub repository.
181
+ * @param remoteFileName - The name of the file in the GitHub release artifact.
182
+ * @returns {Promise<void>}
183
+ */
184
+ async function downloadBinIfNotExists({ localFilePath, dirPath, owner, repoName, remoteFileName, tag, }) {
185
+ if (!fs.existsSync(dirPath)) {
186
+ fs.mkdirSync(dirPath, { recursive: true });
187
+ }
188
+ // Check if file exists
189
+ if (await fileExists(localFilePath)) {
190
+ return;
191
+ }
192
+ if (!tag)
193
+ tag = await latestRelease(owner, repoName);
194
+ const url = `https://github.com/${owner}/${repoName}/releases/download/${tag}/${remoteFileName}`;
195
+ await downloadFile({
196
+ localFilePath,
197
+ dirPath,
198
+ url,
199
+ });
200
+ // Wait for a second to make sure the file is written
201
+ await (0, stateless_js_1.sleep)(1000);
202
+ }
203
+ exports.downloadBinIfNotExists = downloadBinIfNotExists;
@@ -0,0 +1 @@
1
+ export * from "./download";
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./download"), exports);
@@ -0,0 +1,14 @@
1
+ export declare const SPL_NOOP_PROGRAM_TAG = "spl-noop-v0.2.0";
2
+ export declare const LIGHT_MERKLE_TREE_PROGRAM_TAG = "light-merkle-tree-program-v0.3.1";
3
+ export declare const CONFIG_PATH = "/.config/light/";
4
+ export declare const CONFIG_FILE_NAME = "config.json";
5
+ export declare const DEFAULT_CONFIG: {
6
+ solanaRpcUrl: string;
7
+ };
8
+ export declare const CARGO_GENERATE_TAG = "v0.18.4";
9
+ export declare const SOLANA_VALIDATOR_PROCESS_NAME = "solana-test-validator";
10
+ export declare const LIGHT_PROVER_PROCESS_NAME = "light-prover";
11
+ export declare const INDEXER_PROCESS_NAME = "photon";
12
+ export declare const PHOTON_VERSION = "0.18.0";
13
+ export declare const LIGHT_PROTOCOL_PROGRAMS_DIR_ENV = "LIGHT_PROTOCOL_PROGRAMS_DIR";
14
+ export declare const BASE_PATH = "../../bin/";
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BASE_PATH = exports.LIGHT_PROTOCOL_PROGRAMS_DIR_ENV = exports.PHOTON_VERSION = exports.INDEXER_PROCESS_NAME = exports.LIGHT_PROVER_PROCESS_NAME = exports.SOLANA_VALIDATOR_PROCESS_NAME = exports.CARGO_GENERATE_TAG = exports.DEFAULT_CONFIG = exports.CONFIG_FILE_NAME = exports.CONFIG_PATH = exports.LIGHT_MERKLE_TREE_PROGRAM_TAG = exports.SPL_NOOP_PROGRAM_TAG = void 0;
4
+ exports.SPL_NOOP_PROGRAM_TAG = "spl-noop-v0.2.0";
5
+ exports.LIGHT_MERKLE_TREE_PROGRAM_TAG = "light-merkle-tree-program-v0.3.1";
6
+ exports.CONFIG_PATH = "/.config/light/";
7
+ exports.CONFIG_FILE_NAME = "config.json";
8
+ exports.DEFAULT_CONFIG = {
9
+ solanaRpcUrl: "http://127.0.0.1:8899",
10
+ };
11
+ // TODO: investigate why latest cargo-generate fails
12
+ // Fixed version because 11/11/23 release (v0.18.5) fails
13
+ exports.CARGO_GENERATE_TAG = "v0.18.4";
14
+ exports.SOLANA_VALIDATOR_PROCESS_NAME = "solana-test-validator";
15
+ exports.LIGHT_PROVER_PROCESS_NAME = "light-prover";
16
+ exports.INDEXER_PROCESS_NAME = "photon";
17
+ exports.PHOTON_VERSION = "0.18.0";
18
+ exports.LIGHT_PROTOCOL_PROGRAMS_DIR_ENV = "LIGHT_PROTOCOL_PROGRAMS_DIR";
19
+ exports.BASE_PATH = "../../bin/";
@@ -0,0 +1,5 @@
1
+ export * from "./utils";
2
+ export * from "./initTestEnv";
3
+ export * from "./processPhotonIndexer";
4
+ export * from "./processProverServer";
5
+ export * from "./constants";
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./utils"), exports);
5
+ tslib_1.__exportStar(require("./initTestEnv"), exports);
6
+ tslib_1.__exportStar(require("./processPhotonIndexer"), exports);
7
+ tslib_1.__exportStar(require("./processProverServer"), exports);
8
+ tslib_1.__exportStar(require("./constants"), exports);
@@ -0,0 +1,38 @@
1
+ export declare function initTestEnv({ additionalPrograms, skipSystemAccounts, indexer, prover, proveCompressedAccounts, proveNewAddresses, checkPhotonVersion, photonDatabaseUrl, }: {
2
+ additionalPrograms?: {
3
+ address: string;
4
+ path: string;
5
+ }[];
6
+ skipSystemAccounts?: boolean;
7
+ indexer: boolean;
8
+ prover: boolean;
9
+ proveCompressedAccounts?: boolean;
10
+ proveNewAddresses?: boolean;
11
+ checkPhotonVersion?: boolean;
12
+ photonDatabaseUrl?: string;
13
+ }): Promise<void>;
14
+ export declare function initTestEnvIfNeeded({ additionalPrograms, skipSystemAccounts, indexer, prover, }?: {
15
+ additionalPrograms?: {
16
+ address: string;
17
+ path: string;
18
+ }[];
19
+ skipSystemAccounts?: boolean;
20
+ indexer?: boolean;
21
+ prover?: boolean;
22
+ }): Promise<void>;
23
+ export declare function getSolanaArgs({ additionalPrograms, skipSystemAccounts, downloadBinaries, }: {
24
+ additionalPrograms?: {
25
+ address: string;
26
+ path: string;
27
+ }[];
28
+ skipSystemAccounts?: boolean;
29
+ downloadBinaries?: boolean;
30
+ }): Promise<Array<string>>;
31
+ export declare function startTestValidator({ additionalPrograms, skipSystemAccounts, }: {
32
+ additionalPrograms?: {
33
+ address: string;
34
+ path: string;
35
+ }[];
36
+ skipSystemAccounts?: boolean;
37
+ }): Promise<void>;
38
+ export declare function killTestValidator(): Promise<void>;
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.killTestValidator = exports.startTestValidator = exports.getSolanaArgs = exports.initTestEnvIfNeeded = exports.initTestEnv = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const stateless_js_1 = require("@lightprotocol/stateless.js");
6
+ const utils_1 = require("./utils");
7
+ const constants_1 = require("./constants");
8
+ const path_1 = tslib_1.__importDefault(require("path"));
9
+ const psp_utils_1 = require("../psp-utils");
10
+ const process_1 = require("./process");
11
+ const processProverServer_1 = require("./processProverServer");
12
+ const processPhotonIndexer_1 = require("./processPhotonIndexer");
13
+ async function initTestEnv({ additionalPrograms, skipSystemAccounts, indexer = true, prover = true, proveCompressedAccounts = true, proveNewAddresses = false, checkPhotonVersion = true, photonDatabaseUrl, }) {
14
+ console.log("Performing setup tasks...\n");
15
+ const initAccounts = async () => {
16
+ const anchorProvider = await (0, utils_1.setAnchorProvider)();
17
+ const payer = await (0, utils_1.getPayer)();
18
+ await (0, stateless_js_1.airdropSol)({
19
+ connection: anchorProvider.connection,
20
+ lamports: 100e9,
21
+ recipientPublicKey: payer.publicKey,
22
+ });
23
+ };
24
+ // We cannot await this promise directly because it will hang the process
25
+ startTestValidator({ additionalPrograms, skipSystemAccounts });
26
+ await (0, process_1.waitForServers)([{ port: 8899, path: "/health" }]);
27
+ await (0, process_1.confirmServerStability)("http://127.0.0.1:8899/health");
28
+ await initAccounts();
29
+ if (indexer) {
30
+ await (0, processPhotonIndexer_1.startIndexer)(checkPhotonVersion, photonDatabaseUrl);
31
+ }
32
+ if (prover) {
33
+ await (0, processProverServer_1.startProver)(proveCompressedAccounts, proveNewAddresses);
34
+ }
35
+ }
36
+ exports.initTestEnv = initTestEnv;
37
+ async function initTestEnvIfNeeded({ additionalPrograms, skipSystemAccounts, indexer = false, prover = false, } = {}) {
38
+ try {
39
+ const anchorProvider = await (0, utils_1.setAnchorProvider)();
40
+ // this request will fail if there is no local test validator running
41
+ const payer = await (0, utils_1.getPayer)();
42
+ await anchorProvider.connection.getBalance(payer.publicKey);
43
+ }
44
+ catch (error) {
45
+ // launch local test validator and initialize test environment
46
+ await initTestEnv({
47
+ additionalPrograms,
48
+ skipSystemAccounts,
49
+ indexer,
50
+ prover,
51
+ });
52
+ }
53
+ }
54
+ exports.initTestEnvIfNeeded = initTestEnvIfNeeded;
55
+ /*
56
+ * Determines a path to which Light Protocol programs should be downloaded.
57
+ *
58
+ * If the `LIGHT_PROTOCOL_PROGRAMS_DIR` environment variable is set, the path
59
+ * provided in it is used.
60
+ *
61
+ * Otherwise, the `bin` directory in the CLI internals is used.
62
+ *
63
+ * @returns {string} Directory path for Light Protocol programs.
64
+ */
65
+ function programsDirPath() {
66
+ return (process.env[constants_1.LIGHT_PROTOCOL_PROGRAMS_DIR_ENV] ||
67
+ path_1.default.resolve(__dirname, constants_1.BASE_PATH));
68
+ }
69
+ /*
70
+ * Determines a patch to which the given program should be downloaded.
71
+ *
72
+ * If the `LIGHT_PROTOCOL_PROGRAMS_DIR` environment variable is set, the path
73
+ * provided in it is used as a parent
74
+ *
75
+ * Otherwise, the `bin` directory in the CLI internals is used.
76
+ *
77
+ * @returns {string} Path for the given program.
78
+ */
79
+ function programFilePath(programName) {
80
+ const programsDir = process.env[constants_1.LIGHT_PROTOCOL_PROGRAMS_DIR_ENV];
81
+ if (programsDir) {
82
+ return path_1.default.join(programsDir, programName);
83
+ }
84
+ return path_1.default.resolve(__dirname, path_1.default.join(constants_1.BASE_PATH, programName));
85
+ }
86
+ async function getSolanaArgs({ additionalPrograms, skipSystemAccounts, downloadBinaries = true, }) {
87
+ const LIMIT_LEDGER_SIZE = "500000000";
88
+ // TODO: adjust program tags
89
+ const programs = [
90
+ {
91
+ id: "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV",
92
+ name: "spl_noop.so",
93
+ tag: constants_1.SPL_NOOP_PROGRAM_TAG,
94
+ },
95
+ {
96
+ id: "6UqiSPd2mRCTTwkzhcs1M6DGYsqHWd5jiPueX3LwDMXQ",
97
+ name: "light_system_program.so",
98
+ tag: constants_1.LIGHT_MERKLE_TREE_PROGRAM_TAG,
99
+ },
100
+ {
101
+ id: "9sixVEthz2kMSKfeApZXHwuboT6DZuT6crAYJTciUCqE",
102
+ name: "light_compressed_token.so",
103
+ tag: constants_1.LIGHT_MERKLE_TREE_PROGRAM_TAG,
104
+ },
105
+ {
106
+ id: "5QPEJ5zDsVou9FQS3KCauKswM3VwBEBu4dpL9xTqkWwN",
107
+ name: "account_compression.so",
108
+ tag: constants_1.LIGHT_MERKLE_TREE_PROGRAM_TAG,
109
+ },
110
+ {
111
+ id: "5WzvRtu7LABotw1SUEpguJiKU27LRGsiCnF5FH6VV7yP",
112
+ name: "light_registry.so",
113
+ tag: constants_1.LIGHT_MERKLE_TREE_PROGRAM_TAG,
114
+ },
115
+ ];
116
+ if (additionalPrograms)
117
+ additionalPrograms.forEach((program) => {
118
+ programs.push({ id: program.address, path: program.path });
119
+ });
120
+ const dirPath = programsDirPath();
121
+ const solanaArgs = [
122
+ "--reset",
123
+ `--limit-ledger-size=${LIMIT_LEDGER_SIZE}`,
124
+ "--quiet",
125
+ ];
126
+ for (const program of programs) {
127
+ if (program.path) {
128
+ solanaArgs.push("--bpf-program", program.id, program.path);
129
+ }
130
+ else {
131
+ const localFilePath = programFilePath(program.name);
132
+ if (program.name === "spl_noop.so" || downloadBinaries) {
133
+ await (0, psp_utils_1.downloadBinIfNotExists)({
134
+ localFilePath,
135
+ dirPath,
136
+ owner: "Lightprotocol",
137
+ repoName: "light-protocol",
138
+ remoteFileName: program.name,
139
+ tag: program.tag,
140
+ });
141
+ }
142
+ solanaArgs.push("--bpf-program", program.id, localFilePath);
143
+ }
144
+ }
145
+ if (!skipSystemAccounts) {
146
+ const accountsRelPath = "../../accounts";
147
+ const accountsPath = path_1.default.resolve(__dirname, accountsRelPath);
148
+ solanaArgs.push("--account-dir", accountsPath);
149
+ }
150
+ return solanaArgs;
151
+ }
152
+ exports.getSolanaArgs = getSolanaArgs;
153
+ async function startTestValidator({ additionalPrograms, skipSystemAccounts, }) {
154
+ const command = "solana-test-validator";
155
+ const solanaArgs = await getSolanaArgs({
156
+ additionalPrograms,
157
+ skipSystemAccounts,
158
+ });
159
+ await killTestValidator();
160
+ await new Promise((r) => setTimeout(r, 1000));
161
+ console.log("Starting test validator...", command);
162
+ await (0, process_1.executeCommand)({
163
+ command,
164
+ args: [...solanaArgs],
165
+ });
166
+ }
167
+ exports.startTestValidator = startTestValidator;
168
+ async function killTestValidator() {
169
+ await (0, process_1.killProcess)("solana-test-validator");
170
+ }
171
+ exports.killTestValidator = killTestValidator;
@@ -0,0 +1,30 @@
1
+ export declare function killProcess(processName: string): Promise<void>;
2
+ export declare function killProcessByPort(port: string): Promise<void>;
3
+ /**
4
+ * Executes a command and logs the output to the console.
5
+ * @param command - Path to the command to be executed.
6
+ * @param args - Arguments to be passed to the command.
7
+ * @param additionalPath - Additional path to be added to the PATH environment
8
+ * variable.
9
+ */
10
+ export declare function executeCommand({ command, args, additionalPath, logFile, }: {
11
+ command: string;
12
+ args: string[];
13
+ additionalPath?: string;
14
+ logFile?: boolean;
15
+ }): Promise<string>;
16
+ /**
17
+ * Executes a shell command and returns a promise that resolves to the output of the shell command, or an error.
18
+ *
19
+ * @param command A shell command to execute
20
+ * @returns Promise that resolves to string output of shell command
21
+ * @throws {Error} If shell command execution fails
22
+ * @example const output = await execute("ls -alh");
23
+ */
24
+ export declare function execute(command: string): Promise<string>;
25
+ export declare function spawnBinary(command: string, args?: string[]): void;
26
+ export declare function waitForServers(servers: {
27
+ port: number;
28
+ path: string;
29
+ }[]): Promise<void>;
30
+ export declare function confirmServerStability(url: string, attempts?: number): Promise<void>;
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.confirmServerStability = exports.waitForServers = exports.spawnBinary = exports.execute = exports.executeCommand = exports.killProcessByPort = exports.killProcess = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const child_process_1 = require("child_process");
6
+ const path_1 = tslib_1.__importDefault(require("path"));
7
+ const fs_1 = tslib_1.__importDefault(require("fs"));
8
+ const find_process_1 = tslib_1.__importDefault(require("find-process"));
9
+ const node_child_process_1 = require("node:child_process");
10
+ const util_1 = require("util");
11
+ const axios_1 = tslib_1.__importDefault(require("axios"));
12
+ const waitOn = require("wait-on");
13
+ async function killProcess(processName) {
14
+ const processList = await (0, find_process_1.default)("name", processName);
15
+ const targetProcesses = processList.filter((proc) => proc.cmd.split(" ")[0] === processName);
16
+ targetProcesses.forEach((proc) => {
17
+ process.kill(proc.pid);
18
+ });
19
+ }
20
+ exports.killProcess = killProcess;
21
+ async function killProcessByPort(port) {
22
+ await execute("lsof -t -i:3001 | while read line; do kill -9 $line; done");
23
+ }
24
+ exports.killProcessByPort = killProcessByPort;
25
+ /**
26
+ * Executes a command and logs the output to the console.
27
+ * @param command - Path to the command to be executed.
28
+ * @param args - Arguments to be passed to the command.
29
+ * @param additionalPath - Additional path to be added to the PATH environment
30
+ * variable.
31
+ */
32
+ async function executeCommand({ command, args, additionalPath, logFile = true, }) {
33
+ return new Promise((resolve, reject) => {
34
+ const commandBase = path_1.default.basename(command);
35
+ let stdoutData = "";
36
+ const childPathEnv = additionalPath
37
+ ? process.env.PATH + path_1.default.delimiter + additionalPath
38
+ : process.env.PATH;
39
+ const options = {
40
+ env: childPathEnv ? { ...process.env, PATH: childPathEnv } : process.env,
41
+ detached: true,
42
+ };
43
+ if (logFile) {
44
+ const folderName = "test-ledger";
45
+ const file = `./${folderName}/${commandBase}.log`;
46
+ if (!fs_1.default.existsSync(folderName)) {
47
+ fs_1.default.mkdirSync(folderName);
48
+ }
49
+ const logStream = fs_1.default.createWriteStream(file, {
50
+ flags: "a",
51
+ });
52
+ process.stdout.pipe(logStream);
53
+ process.stderr.pipe(logStream);
54
+ }
55
+ console.log(`Executing command ${commandBase} ${args}...`);
56
+ let childProcess;
57
+ try {
58
+ childProcess = (0, child_process_1.spawn)(command, args, options);
59
+ }
60
+ catch (e) {
61
+ throw new Error(`Failed to execute command ${commandBase}: ${e}`);
62
+ }
63
+ childProcess.stdout.on("data", (data) => {
64
+ stdoutData += data.toString();
65
+ process.stdout.write(data);
66
+ });
67
+ childProcess.stderr.on("data", (data) => {
68
+ process.stderr.write(data);
69
+ });
70
+ childProcess.on("close", (code) => {
71
+ if (code !== 0) {
72
+ console.log(`${commandBase} exited with code ${code}`);
73
+ reject(new Error(`${commandBase} exited with code ${code}`));
74
+ }
75
+ else {
76
+ console.log(`${commandBase} finished successfully!`);
77
+ resolve(stdoutData);
78
+ }
79
+ });
80
+ });
81
+ }
82
+ exports.executeCommand = executeCommand;
83
+ const exec = (0, util_1.promisify)(node_child_process_1.exec);
84
+ /**
85
+ * Executes a shell command and returns a promise that resolves to the output of the shell command, or an error.
86
+ *
87
+ * @param command A shell command to execute
88
+ * @returns Promise that resolves to string output of shell command
89
+ * @throws {Error} If shell command execution fails
90
+ * @example const output = await execute("ls -alh");
91
+ */
92
+ async function execute(command) {
93
+ try {
94
+ const { stdout } = await exec(command);
95
+ return stdout;
96
+ }
97
+ catch (err) {
98
+ console.log("Error in `execute`: ", err);
99
+ throw err;
100
+ }
101
+ }
102
+ exports.execute = execute;
103
+ function spawnBinary(command, args = []) {
104
+ const logDir = "test-ledger";
105
+ const binaryName = path_1.default.basename(command);
106
+ const dir = path_1.default.join(__dirname, logDir);
107
+ if (!fs_1.default.existsSync(dir)) {
108
+ fs_1.default.mkdirSync(dir);
109
+ }
110
+ const out = fs_1.default.openSync(`${logDir}/${binaryName}.log`, "a");
111
+ const err = fs_1.default.openSync(`${logDir}/${binaryName}.log`, "a");
112
+ const spawnedProcess = (0, child_process_1.spawn)(command, args, {
113
+ stdio: ["ignore", out, err],
114
+ shell: false,
115
+ detached: true,
116
+ });
117
+ spawnedProcess.on("close", (code) => {
118
+ console.log(`${binaryName} process exited with code ${code}`);
119
+ });
120
+ }
121
+ exports.spawnBinary = spawnBinary;
122
+ async function waitForServers(servers) {
123
+ const opts = {
124
+ resources: servers.map(({ port, path }) => `http-get://127.0.0.1:${port}${path}`),
125
+ delay: 1000,
126
+ timeout: 15000,
127
+ interval: 300,
128
+ simultaneous: 2,
129
+ validateStatus: function (status) {
130
+ return ((status >= 200 && status < 300) || status === 404 || status === 405);
131
+ },
132
+ };
133
+ try {
134
+ await waitOn(opts);
135
+ servers.forEach((server) => {
136
+ console.log(`${server.port} is up!`);
137
+ });
138
+ }
139
+ catch (err) {
140
+ console.error("Error waiting for server to start:", err);
141
+ throw err;
142
+ }
143
+ }
144
+ exports.waitForServers = waitForServers;
145
+ // Solana test validator can be unreliable when starting up.
146
+ async function confirmServerStability(url, attempts = 20) {
147
+ try {
148
+ for (let i = 0; i < attempts; i++) {
149
+ const response = await axios_1.default.get(url);
150
+ if (response.status !== 200) {
151
+ throw new Error("Server failed stability check");
152
+ }
153
+ await new Promise((resolve) => setTimeout(resolve, 300));
154
+ }
155
+ console.log("Server has passed stability checks.");
156
+ }
157
+ catch (error) {
158
+ console.error("Server stability check failed:", error);
159
+ throw error;
160
+ }
161
+ }
162
+ exports.confirmServerStability = confirmServerStability;
@@ -0,0 +1 @@
1
+ export declare function startIndexer(checkPhotonVersion?: boolean, photonDatabaseUrl?: string): Promise<void>;