@voidifydao/sdk 1.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.
Files changed (115) hide show
  1. package/dist/cli/config/command.d.ts +2 -0
  2. package/dist/cli/config/command.js +91 -0
  3. package/dist/cli/config/init.d.ts +3 -0
  4. package/dist/cli/config/init.js +88 -0
  5. package/dist/cli/config/keypair.d.ts +4 -0
  6. package/dist/cli/config/keypair.js +35 -0
  7. package/dist/cli/config/loader.d.ts +11 -0
  8. package/dist/cli/config/loader.js +65 -0
  9. package/dist/cli/config/types.d.ts +50 -0
  10. package/dist/cli/config/types.js +33 -0
  11. package/dist/cli/deposit.d.ts +2 -0
  12. package/dist/cli/deposit.js +58 -0
  13. package/dist/cli/helpers.d.ts +12 -0
  14. package/dist/cli/helpers.js +53 -0
  15. package/dist/cli/note.d.ts +2 -0
  16. package/dist/cli/note.js +50 -0
  17. package/dist/cli/relayer.d.ts +2 -0
  18. package/dist/cli/relayer.js +60 -0
  19. package/dist/cli/substream.d.ts +2 -0
  20. package/dist/cli/substream.js +35 -0
  21. package/dist/cli/withdraw.d.ts +2 -0
  22. package/dist/cli/withdraw.js +23 -0
  23. package/dist/cli.d.ts +2 -0
  24. package/dist/cli.js +30 -0
  25. package/dist/context.d.ts +45 -0
  26. package/dist/context.js +77 -0
  27. package/dist/idl/voidify/idl.d.ts +1313 -0
  28. package/dist/idl/voidify/idl.js +1 -0
  29. package/dist/idl/voidify/idl.json +1307 -0
  30. package/dist/idl/voidify-staking/idl.d.ts +93 -0
  31. package/dist/idl/voidify-staking/idl.js +1 -0
  32. package/dist/idl/voidify-staking/idl.json +87 -0
  33. package/dist/index.d.ts +17 -0
  34. package/dist/index.js +10 -0
  35. package/dist/relayer/server/index.d.ts +6 -0
  36. package/dist/relayer/server/index.js +32 -0
  37. package/dist/relayer/server/server.d.ts +24 -0
  38. package/dist/relayer/server/server.js +158 -0
  39. package/dist/relayer/server/switchboard.d.ts +2 -0
  40. package/dist/relayer/server/switchboard.js +42 -0
  41. package/dist/relayer/types.d.ts +21 -0
  42. package/dist/relayer/types.js +1 -0
  43. package/dist/staking/commands.d.ts +3 -0
  44. package/dist/staking/commands.js +13 -0
  45. package/dist/staking/index.d.ts +2 -0
  46. package/dist/staking/index.js +2 -0
  47. package/dist/staking/program.d.ts +18 -0
  48. package/dist/staking/program.js +40 -0
  49. package/dist/substream/chain/events.d.ts +4 -0
  50. package/dist/substream/chain/events.js +50 -0
  51. package/dist/substream/chain/index.d.ts +24 -0
  52. package/dist/substream/chain/index.js +79 -0
  53. package/dist/substream/chain/registry.d.ts +44 -0
  54. package/dist/substream/chain/registry.js +28 -0
  55. package/dist/substream/chain/utils.d.ts +9 -0
  56. package/dist/substream/chain/utils.js +41 -0
  57. package/dist/substream/client.d.ts +27 -0
  58. package/dist/substream/client.js +28 -0
  59. package/dist/substream/database/indexeddb.d.ts +2 -0
  60. package/dist/substream/database/indexeddb.js +242 -0
  61. package/dist/substream/database/sqlite.d.ts +26 -0
  62. package/dist/substream/database/sqlite.js +275 -0
  63. package/dist/substream/modules/deposit.d.ts +14 -0
  64. package/dist/substream/modules/deposit.js +123 -0
  65. package/dist/substream/modules/index.d.ts +11 -0
  66. package/dist/substream/modules/index.js +7 -0
  67. package/dist/substream/modules/relayer.d.ts +10 -0
  68. package/dist/substream/modules/relayer.js +290 -0
  69. package/dist/substream/runtime.d.ts +38 -0
  70. package/dist/substream/runtime.js +163 -0
  71. package/dist/substream/server/event-listener.d.ts +18 -0
  72. package/dist/substream/server/event-listener.js +68 -0
  73. package/dist/substream/server/index.d.ts +3 -0
  74. package/dist/substream/server/index.js +30 -0
  75. package/dist/substream/server/server.d.ts +43 -0
  76. package/dist/substream/server/server.js +216 -0
  77. package/dist/substream/types.d.ts +94 -0
  78. package/dist/substream/types.js +1 -0
  79. package/dist/types/errors.d.ts +1 -0
  80. package/dist/types/errors.js +16 -0
  81. package/dist/types/events.d.ts +13 -0
  82. package/dist/types/events.js +1 -0
  83. package/dist/types/index.d.ts +3 -0
  84. package/dist/types/index.js +1 -0
  85. package/dist/utils/amount.d.ts +4 -0
  86. package/dist/utils/amount.js +41 -0
  87. package/dist/utils/anchor-events.d.ts +13 -0
  88. package/dist/utils/anchor-events.js +28 -0
  89. package/dist/utils/bytes.d.ts +10 -0
  90. package/dist/utils/bytes.js +29 -0
  91. package/dist/utils/idl-seed.d.ts +17 -0
  92. package/dist/utils/idl-seed.js +15 -0
  93. package/dist/utils/index.d.ts +2 -0
  94. package/dist/utils/index.js +2 -0
  95. package/dist/utils/logger.d.ts +3 -0
  96. package/dist/utils/logger.js +19 -0
  97. package/dist/utils/note.d.ts +19 -0
  98. package/dist/utils/note.js +83 -0
  99. package/dist/utils/proof.d.ts +11 -0
  100. package/dist/utils/proof.js +91 -0
  101. package/dist/utils/tx.d.ts +11 -0
  102. package/dist/utils/tx.js +62 -0
  103. package/dist/voidify/deposit.d.ts +10 -0
  104. package/dist/voidify/deposit.js +40 -0
  105. package/dist/voidify/index.d.ts +4 -0
  106. package/dist/voidify/index.js +4 -0
  107. package/dist/voidify/program.d.ts +36 -0
  108. package/dist/voidify/program.js +87 -0
  109. package/dist/voidify/relayer/index.d.ts +1 -0
  110. package/dist/voidify/relayer/index.js +1 -0
  111. package/dist/voidify/relayer/list.d.ts +5 -0
  112. package/dist/voidify/relayer/list.js +16 -0
  113. package/dist/voidify/withdraw.d.ts +16 -0
  114. package/dist/voidify/withdraw.js +188 -0
  115. package/package.json +79 -0
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerConfigCommand(program: Command): void;
@@ -0,0 +1,91 @@
1
+ import { Command } from "commander";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { defaultUserConfigPath, getStore, getStorePath, isValidConfigKey, } from "./loader.js";
5
+ import { buildTemplate, postInitHint } from "./init.js";
6
+ function requireConfigPath(cmd) {
7
+ const root = cmd.parent?.parent ?? cmd.parent ?? cmd;
8
+ const cfgPath = root.opts().config;
9
+ return cfgPath ?? defaultUserConfigPath();
10
+ }
11
+ const VALID_INIT_TYPES = [
12
+ "default",
13
+ "relayer",
14
+ "substream",
15
+ "full",
16
+ ];
17
+ function parseInitType(raw) {
18
+ if (VALID_INIT_TYPES.includes(raw)) {
19
+ return raw;
20
+ }
21
+ console.error(`Unknown --type: ${raw}. Available values: ${VALID_INIT_TYPES.join(", ")}`);
22
+ process.exit(1);
23
+ }
24
+ function resolveInitPath(cmd, initPath) {
25
+ if (initPath)
26
+ return initPath;
27
+ const root = cmd.parent?.parent ?? cmd.parent ?? cmd;
28
+ const fromGlobal = root.opts().config;
29
+ if (fromGlobal)
30
+ return fromGlobal;
31
+ return defaultUserConfigPath();
32
+ }
33
+ export function registerConfigCommand(program) {
34
+ const configCommand = new Command("config")
35
+ .enablePositionalOptions()
36
+ .description("Client config file management; does not affect on-chain program state");
37
+ configCommand
38
+ .command("path")
39
+ .description("Print the config file path; requires -c <path>")
40
+ .action(function () {
41
+ console.log(getStorePath(requireConfigPath(this)));
42
+ });
43
+ configCommand
44
+ .command("init")
45
+ .description("Write the initial config only if the file does not exist. --type selects the template and default filename; --path or global -c overrides the location.")
46
+ .option("-t, --type <type>", `Template type: ${VALID_INIT_TYPES.join(" | ")}`, "default")
47
+ .option("--path <path>", "Config file path; defaults to ~/.config/voidify/config.json, or %APPDATA%\\voidify\\config.json on Windows; can also be specified with global -c")
48
+ .action(function (opts) {
49
+ const type = parseInitType(opts.type);
50
+ const filePath = getStorePath(resolveInitPath(this, opts.path));
51
+ if (fs.existsSync(filePath)) {
52
+ console.log(`Config file already exists: ${filePath}`);
53
+ return;
54
+ }
55
+ const template = buildTemplate(type);
56
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
57
+ fs.writeFileSync(filePath, JSON.stringify(template, null, 2) + "\n");
58
+ console.log(`Wrote [${type}] template: ${filePath}`);
59
+ console.log("");
60
+ console.log(postInitHint(type));
61
+ });
62
+ configCommand
63
+ .command("get <key>")
64
+ .description("Read one config item; supports dot notation such as substream.url")
65
+ .action(function (key) {
66
+ const store = getStore(requireConfigPath(this));
67
+ const value = store.get(key);
68
+ console.log(JSON.stringify(value, null, 2));
69
+ });
70
+ configCommand
71
+ .command("set <key> <value>")
72
+ .description("Set one config item; supports dot notation, and falls back to string when JSON parsing fails")
73
+ .action(function (key, raw) {
74
+ if (!isValidConfigKey(key)) {
75
+ console.error(`Unknown config key: ${key}`);
76
+ process.exit(1);
77
+ }
78
+ const store = getStore(requireConfigPath(this));
79
+ let value;
80
+ try {
81
+ value = JSON.parse(raw);
82
+ }
83
+ catch {
84
+ value = raw;
85
+ }
86
+ store.set(key, value);
87
+ console.log(`Wrote: ${key} = ${JSON.stringify(value)}`);
88
+ console.log(`File: ${store.path}`);
89
+ });
90
+ program.addCommand(configCommand);
91
+ }
@@ -0,0 +1,3 @@
1
+ export type InitType = "default" | "relayer" | "substream" | "full";
2
+ export declare function buildTemplate(type: InitType): Record<string, unknown>;
3
+ export declare function postInitHint(type: InitType): string;
@@ -0,0 +1,88 @@
1
+ import { defaults } from "./types.js";
2
+ const REQUIRED = (desc) => `<TODO: ${desc}>`;
3
+ const FILE_KEYPAIR_PATH_HINT = "absolute path to your solana-keygen JSON file";
4
+ function fileKeypairPlaceholder(role) {
5
+ return {
6
+ type: "file",
7
+ path: REQUIRED(`${role} - ${FILE_KEYPAIR_PATH_HINT}`),
8
+ };
9
+ }
10
+ export function buildTemplate(type) {
11
+ switch (type) {
12
+ case "default":
13
+ return {
14
+ rpcUrl: defaults.rpcUrl,
15
+ programId: REQUIRED("voidify program ID"),
16
+ stakingProgramId: null,
17
+ keypair: fileKeypairPlaceholder("user keypair"),
18
+ substream: { ...defaults.substream },
19
+ proof: { ...defaults.proof },
20
+ };
21
+ case "relayer":
22
+ return {
23
+ rpcUrl: defaults.rpcUrl,
24
+ programId: REQUIRED("voidify program ID"),
25
+ stakingProgramId: null,
26
+ keypair: fileKeypairPlaceholder("relayer keypair"),
27
+ relayerServer: { ...defaults.relayerServer },
28
+ };
29
+ case "substream":
30
+ return {
31
+ rpcUrl: defaults.rpcUrl,
32
+ programId: REQUIRED("voidify program ID"),
33
+ keypair: null,
34
+ substreamServer: { ...defaults.substreamServer },
35
+ };
36
+ case "full":
37
+ return {
38
+ rpcUrl: defaults.rpcUrl,
39
+ programId: REQUIRED("voidify program ID"),
40
+ stakingProgramId: null,
41
+ keypair: fileKeypairPlaceholder("keypair for this config"),
42
+ substream: { ...defaults.substream },
43
+ proof: { ...defaults.proof },
44
+ substreamServer: { ...defaults.substreamServer },
45
+ relayerServer: { ...defaults.relayerServer },
46
+ };
47
+ }
48
+ }
49
+ export function postInitHint(type) {
50
+ switch (type) {
51
+ case "default":
52
+ return [
53
+ "Next steps:",
54
+ " - programId <- voidify main program",
55
+ " - keypair.path <- your keypair JSON file path",
56
+ " - stakingProgramId <- optional staking program ID",
57
+ " (substream / proof already use defaults; no changes needed)",
58
+ "",
59
+ "Applicable commands: deposit / withdraw / note.",
60
+ ].join("\n");
61
+ case "relayer":
62
+ return [
63
+ "Next steps:",
64
+ " - programId <- voidify main program",
65
+ " - keypair.path <- keypair for the relayer service itself",
66
+ " - relayerServer.feedId <- Switchboard on-demand feed ID",
67
+ " - stakingProgramId <- optional staking program ID",
68
+ "",
69
+ "Applicable commands: relayer start / relayer list.",
70
+ ].join("\n");
71
+ case "substream":
72
+ return [
73
+ "Next steps:",
74
+ " - programId <- voidify main program (used to filter on-chain events)",
75
+ " - substreamServer.dbPath <- server's local SQLite DB file path",
76
+ "",
77
+ "Applicable command: substream.",
78
+ ].join("\n");
79
+ case "full":
80
+ return [
81
+ "Next steps: full template; fill in values as needed.",
82
+ " required: programId, keypair.path, relayerServer.feedId",
83
+ " optional: stakingProgramId",
84
+ "",
85
+ "Reminder: one config should use one keypair. Create separate config files and switch with -c when roles differ.",
86
+ ].join("\n");
87
+ }
88
+ }
@@ -0,0 +1,4 @@
1
+ import { Keypair } from "@solana/web3.js";
2
+ import type { KeypairSource, VoidifyConfig } from "./types.js";
3
+ export declare function loadKeypairSource(src: KeypairSource | null | undefined): Keypair | null;
4
+ export declare function resolveKeypair(cfg: VoidifyConfig, cliKeypairPath: string | undefined): Keypair | null;
@@ -0,0 +1,35 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import bs58 from "bs58";
5
+ import { Keypair } from "@solana/web3.js";
6
+ function expandHome(p) {
7
+ if (p === "~")
8
+ return os.homedir();
9
+ if (p.startsWith("~/"))
10
+ return path.join(os.homedir(), p.slice(2));
11
+ return p;
12
+ }
13
+ export function loadKeypairSource(src) {
14
+ if (!src)
15
+ return null;
16
+ switch (src.type) {
17
+ case "file": {
18
+ const data = JSON.parse(fs.readFileSync(expandHome(src.path), "utf-8"));
19
+ return Keypair.fromSecretKey(Uint8Array.from(data));
20
+ }
21
+ case "base58": {
22
+ const decoded = bs58.decode(src.key);
23
+ if (decoded.length !== 64) {
24
+ throw new Error(`Decoded keypair base58 value is ${decoded.length} bytes; expected 64 bytes for a standard Solana secret key`);
25
+ }
26
+ return Keypair.fromSecretKey(decoded);
27
+ }
28
+ }
29
+ }
30
+ export function resolveKeypair(cfg, cliKeypairPath) {
31
+ if (cliKeypairPath) {
32
+ return loadKeypairSource({ type: "file", path: cliKeypairPath });
33
+ }
34
+ return loadKeypairSource(cfg.keypair);
35
+ }
@@ -0,0 +1,11 @@
1
+ import Conf from "conf";
2
+ import { type VoidifyConfig } from "./types.js";
3
+ export declare function defaultUserConfigPath(): string;
4
+ export declare function isValidConfigKey(key: string): boolean;
5
+ export interface LoadOptions {
6
+ configPath: string;
7
+ rpcUrl?: string;
8
+ }
9
+ export declare function getStore(configPath: string): Conf<VoidifyConfig>;
10
+ export declare function getStorePath(configPath: string): string;
11
+ export declare function loadConfig(opts: LoadOptions): VoidifyConfig;
@@ -0,0 +1,65 @@
1
+ import Conf from "conf";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { defaultUserConfigDir, defaults } from "./types.js";
5
+ export function defaultUserConfigPath() {
6
+ return path.join(defaultUserConfigDir(), "config.json");
7
+ }
8
+ const OPTIONAL_KEYS = [
9
+ "stakingProgramId",
10
+ "keypair",
11
+ "keypair.type",
12
+ "keypair.path",
13
+ "keypair.key",
14
+ "substream",
15
+ "substream.type",
16
+ "substream.url",
17
+ "substream.dbPath",
18
+ ];
19
+ function collectPaths(obj, prefix = "") {
20
+ if (obj === null || typeof obj !== "object" || Array.isArray(obj))
21
+ return [];
22
+ const paths = [];
23
+ for (const [k, v] of Object.entries(obj)) {
24
+ const next = prefix ? `${prefix}.${k}` : k;
25
+ paths.push(next);
26
+ paths.push(...collectPaths(v, next));
27
+ }
28
+ return paths;
29
+ }
30
+ const VALID_KEYS = new Set([
31
+ ...collectPaths(defaults),
32
+ ...OPTIONAL_KEYS,
33
+ ]);
34
+ export function isValidConfigKey(key) {
35
+ return VALID_KEYS.has(key);
36
+ }
37
+ function buildStore(configPath) {
38
+ const resolved = path.resolve(configPath);
39
+ return new Conf({
40
+ projectName: "voidify",
41
+ cwd: path.dirname(resolved),
42
+ configName: path.basename(resolved, path.extname(resolved)),
43
+ });
44
+ }
45
+ export function getStore(configPath) {
46
+ const resolved = path.resolve(configPath);
47
+ if (!fs.existsSync(resolved)) {
48
+ throw new Error(`Config file does not exist: ${resolved}. Run \`voidify config init [--type ...]\` first to generate a template.`);
49
+ }
50
+ return buildStore(configPath);
51
+ }
52
+ export function getStorePath(configPath) {
53
+ return path.resolve(configPath);
54
+ }
55
+ export function loadConfig(opts) {
56
+ const resolved = path.resolve(opts.configPath);
57
+ if (!fs.existsSync(resolved)) {
58
+ throw new Error(`Config file does not exist: ${resolved}. Run \`voidify config init [--type ...]\` first to generate a template.`);
59
+ }
60
+ const store = buildStore(opts.configPath);
61
+ const cfg = { ...store.store };
62
+ if (opts.rpcUrl)
63
+ cfg.rpcUrl = opts.rpcUrl;
64
+ return cfg;
65
+ }
@@ -0,0 +1,50 @@
1
+ export type KeypairSource = {
2
+ type: "file";
3
+ path: string;
4
+ } | {
5
+ type: "base58";
6
+ key: string;
7
+ };
8
+ export type SubstreamSource = {
9
+ type: "remote";
10
+ url: string;
11
+ dbPath: string;
12
+ } | {
13
+ type: "local";
14
+ dbPath: string;
15
+ } | {
16
+ type: "auto";
17
+ url: string;
18
+ dbPath: string;
19
+ };
20
+ export interface VoidifyConfig {
21
+ rpcUrl: string;
22
+ programId: string;
23
+ stakingProgramId?: string | null;
24
+ keypair?: KeypairSource | null;
25
+ substream?: SubstreamSource | null;
26
+ proof?: {
27
+ wasmPath: string;
28
+ zkeyPath: string;
29
+ } | null;
30
+ substreamServer?: {
31
+ port: number;
32
+ host: string;
33
+ dbPath: string;
34
+ } | null;
35
+ relayerServer?: {
36
+ port: number;
37
+ host: string;
38
+ feedId: string;
39
+ } | null;
40
+ }
41
+ interface VoidifyDefaults {
42
+ rpcUrl: string;
43
+ substream: NonNullable<VoidifyConfig["substream"]>;
44
+ proof: NonNullable<VoidifyConfig["proof"]>;
45
+ substreamServer: NonNullable<VoidifyConfig["substreamServer"]>;
46
+ relayerServer: NonNullable<VoidifyConfig["relayerServer"]>;
47
+ }
48
+ export declare function defaultUserConfigDir(): string;
49
+ export declare const defaults: VoidifyDefaults;
50
+ export {};
@@ -0,0 +1,33 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ export function defaultUserConfigDir() {
4
+ if (process.platform === "win32") {
5
+ const appData = process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming");
6
+ return path.join(appData, "voidify");
7
+ }
8
+ const xdgHome = process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config");
9
+ return path.join(xdgHome, "voidify");
10
+ }
11
+ const defaultConfigPath = (...parts) => path.join(defaultUserConfigDir(), ...parts);
12
+ export const defaults = {
13
+ rpcUrl: "https://api.mainnet-beta.solana.com",
14
+ substream: {
15
+ type: "auto",
16
+ url: "https://substream.voidifycto.com",
17
+ dbPath: defaultConfigPath("substream.db"),
18
+ },
19
+ proof: {
20
+ wasmPath: defaultConfigPath("assets", "withdraw.wasm"),
21
+ zkeyPath: defaultConfigPath("assets", "withdraw.zkey"),
22
+ },
23
+ substreamServer: {
24
+ port: 3003,
25
+ host: "0.0.0.0",
26
+ dbPath: defaultConfigPath("substream-server.db"),
27
+ },
28
+ relayerServer: {
29
+ port: 3002,
30
+ host: "0.0.0.0",
31
+ feedId: "0xc5844a98ff37b7ea928409eb08507e1bfe54f5493c3d7f6012ef9c5e457ec031",
32
+ },
33
+ };
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerDepositCommands(program: Command): void;
@@ -0,0 +1,58 @@
1
+ import { Command } from "commander";
2
+ import { deposit, listDeposits } from "../voidify/deposit.js";
3
+ import { parseUnits } from "../utils/amount.js";
4
+ import { Note } from "../utils/note.js";
5
+ import { createServiceContext, SOL_DECIMALS, } from "../cli/helpers.js";
6
+ export function registerDepositCommands(program) {
7
+ const depositCommand = new Command("deposit")
8
+ .enablePositionalOptions()
9
+ .description("Deposit commands");
10
+ depositCommand
11
+ .command("submit")
12
+ .option("-c, --commitment <string>", "Commitment generated by the note gen command; if omitted, a new one is generated and printed")
13
+ .requiredOption("-a, --amount <amount>", "Deposit amount in UI units, such as 1 for 1 SOL")
14
+ .action(async (options) => {
15
+ try {
16
+ const ctx = await createServiceContext(program.opts());
17
+ let commitment = options.commitment;
18
+ if (!commitment) {
19
+ const note = await Note.generate(options.amount);
20
+ commitment = note.commitment;
21
+ console.log("Note generated:", {
22
+ note: note.serialize(),
23
+ commitment: note.commitment,
24
+ });
25
+ }
26
+ const txSignature = await deposit(ctx, commitment, parseUnits(options.amount, SOL_DECIMALS));
27
+ console.log("Transaction successful:", { txSignature });
28
+ }
29
+ catch (error) {
30
+ console.error("Deposit failed:", error);
31
+ process.exit(1);
32
+ }
33
+ });
34
+ depositCommand
35
+ .command("list <amount>")
36
+ .description("List records for a denomination pool, using UI units such as 1 for 1 SOL")
37
+ .option("--offset <number>", "Pagination offset")
38
+ .option("--limit <number>", "Page size")
39
+ .option("-o, --output <file>", "Write output to a file")
40
+ .action(async (amount, options) => {
41
+ try {
42
+ const ctx = await createServiceContext(program.opts());
43
+ const deposits = await listDeposits(ctx, parseUnits(amount, SOL_DECIMALS), {
44
+ offset: options.offset !== undefined
45
+ ? parseInt(options.offset)
46
+ : undefined,
47
+ limit: options.limit !== undefined ? parseInt(options.limit) : undefined,
48
+ output: options.output,
49
+ });
50
+ console.log("Deposit records:", deposits);
51
+ }
52
+ catch (error) {
53
+ console.error("List deposits failed:", error);
54
+ process.exit(1);
55
+ }
56
+ });
57
+ program.addCommand(depositCommand);
58
+ }
@@ -0,0 +1,12 @@
1
+ import { Context } from "../context.js";
2
+ import type { VoidifyConfig } from "../cli/config/types.js";
3
+ export declare const SOL_DECIMALS = 9;
4
+ export interface GlobalOptions {
5
+ config?: string;
6
+ keypair?: string;
7
+ url?: string;
8
+ }
9
+ export declare function expandHome(p: string): string;
10
+ export declare function loadCliConfig(opts: GlobalOptions): VoidifyConfig;
11
+ export declare function contextFromConfig(cfg: VoidifyConfig, cliKeypairPath?: string): Promise<Context>;
12
+ export declare function createServiceContext(opts: GlobalOptions): Promise<Context>;
@@ -0,0 +1,53 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ import { PublicKey } from "@solana/web3.js";
4
+ import { Context } from "../context.js";
5
+ import { defaultUserConfigPath, loadConfig } from "../cli/config/loader.js";
6
+ import { resolveKeypair } from "../cli/config/keypair.js";
7
+ import { makeSQLiteStores } from "../substream/database/sqlite.js";
8
+ export const SOL_DECIMALS = 9;
9
+ export function expandHome(p) {
10
+ if (p === "~")
11
+ return os.homedir();
12
+ if (p.startsWith("~/"))
13
+ return path.join(os.homedir(), p.slice(2));
14
+ return p;
15
+ }
16
+ export function loadCliConfig(opts) {
17
+ return loadConfig({
18
+ configPath: opts.config ?? defaultUserConfigPath(),
19
+ rpcUrl: opts.url,
20
+ });
21
+ }
22
+ export async function contextFromConfig(cfg, cliKeypairPath) {
23
+ const keypair = resolveKeypair(cfg, cliKeypairPath);
24
+ const substream = (() => {
25
+ const cs = cfg.substream;
26
+ if (!cs)
27
+ return undefined;
28
+ const dbPath = expandHome(cs.dbPath);
29
+ const makeRepos = () => makeSQLiteStores(dbPath, cfg.programId);
30
+ switch (cs.type) {
31
+ case "remote":
32
+ return { type: "remote", url: cs.url, makeRepos };
33
+ case "local":
34
+ return { type: "local", makeRepos };
35
+ case "auto":
36
+ return { type: "auto", url: cs.url, makeRepos };
37
+ }
38
+ })();
39
+ return new Context({
40
+ rpcUrl: cfg.rpcUrl,
41
+ programId: cfg.programId ? new PublicKey(cfg.programId) : undefined,
42
+ stakingProgramId: cfg.stakingProgramId
43
+ ? new PublicKey(cfg.stakingProgramId)
44
+ : undefined,
45
+ wallet: keypair,
46
+ substream,
47
+ wasmPath: cfg.proof ? expandHome(cfg.proof.wasmPath) : undefined,
48
+ zkeyPath: cfg.proof ? expandHome(cfg.proof.zkeyPath) : undefined,
49
+ });
50
+ }
51
+ export async function createServiceContext(opts) {
52
+ return contextFromConfig(loadCliConfig(opts), opts.keypair);
53
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerNoteCommands(program: Command): void;
@@ -0,0 +1,50 @@
1
+ import { Command } from "commander";
2
+ import { Note } from "../utils/note.js";
3
+ import { formatUnits } from "../utils/amount.js";
4
+ import { SOL_DECIMALS } from "../cli/helpers.js";
5
+ export function registerNoteCommands(program) {
6
+ const noteCommand = new Command("note")
7
+ .enablePositionalOptions()
8
+ .description("Generate notes");
9
+ noteCommand
10
+ .command("gen <amount>")
11
+ .description("Generate a note; amount uses UI units such as 1 for 1 SOL")
12
+ .action(async (amount) => {
13
+ try {
14
+ const note = await Note.generate(amount);
15
+ console.log("Note generated:", {
16
+ note: note.serialize(),
17
+ commitment: note.commitment,
18
+ });
19
+ }
20
+ catch (error) {
21
+ console.error("Generate note failed:", error);
22
+ process.exit(1);
23
+ }
24
+ });
25
+ noteCommand
26
+ .command("verify <note> <commitment>")
27
+ .description("Verify a note")
28
+ .action(async (note_str, commitment) => {
29
+ try {
30
+ const note = await Note.deserialize(note_str);
31
+ const valid = await note.verify(commitment);
32
+ if (!valid) {
33
+ console.error("Note is invalid");
34
+ process.exit(1);
35
+ }
36
+ console.log("Note verification passed");
37
+ console.log("Note details:", {
38
+ amount: note.amount,
39
+ amountInSol: formatUnits(note.amountRaw, SOL_DECIMALS),
40
+ commitment: note.commitment,
41
+ nullifierHash: note.nullifierHash,
42
+ });
43
+ }
44
+ catch (error) {
45
+ console.error("Note verify failed:", error);
46
+ process.exit(1);
47
+ }
48
+ });
49
+ program.addCommand(noteCommand);
50
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerRelayerCommands(program: Command): void;
@@ -0,0 +1,60 @@
1
+ import { Command } from "commander";
2
+ import { startRelayer } from "../relayer/server/index.js";
3
+ import { listRelayers } from "../voidify/relayer/list.js";
4
+ import { createServiceContext, contextFromConfig, loadCliConfig, } from "../cli/helpers.js";
5
+ export function registerRelayerCommands(program) {
6
+ const relayerCommand = new Command("relayer")
7
+ .enablePositionalOptions()
8
+ .description("Relayer commands");
9
+ relayerCommand
10
+ .command("list")
11
+ .description("List relayer information; with --pubkey, returns only that relayer")
12
+ .option("--pubkey <pubkey>", "Specific relayer public key")
13
+ .option("-o, --output <file>", "Write output to a file")
14
+ .action(async (options) => {
15
+ try {
16
+ const ctx = await createServiceContext(program.opts());
17
+ const relayers = await listRelayers(ctx, options.pubkey, {
18
+ output: options.output,
19
+ });
20
+ console.log("Relayer records:", relayers);
21
+ }
22
+ catch (error) {
23
+ console.error("List relayers failed:", error);
24
+ process.exit(1);
25
+ }
26
+ });
27
+ relayerCommand
28
+ .command("start")
29
+ .description("Start the relayer HTTP service")
30
+ .option("--port <number>", "Service port")
31
+ .option("--host <host>", "Service listen address")
32
+ .action(async (options) => {
33
+ try {
34
+ const opts = program.opts();
35
+ const cfg = loadCliConfig(opts);
36
+ if (!cfg.relayerServer) {
37
+ throw new Error("relayerServer is not configured. Set relayerServer to {port, host, feedId}, or rerun `voidify-cli config init --type relayer`.");
38
+ }
39
+ const feedId = cfg.relayerServer.feedId;
40
+ if (!feedId) {
41
+ throw new Error("relayerServer.feedId is not configured. Run `voidify-cli config set relayerServer.feedId <0x...>`.");
42
+ }
43
+ const ctx = await contextFromConfig(cfg, opts.keypair);
44
+ const port = options.port
45
+ ? parseInt(options.port)
46
+ : cfg.relayerServer.port;
47
+ const host = options.host ?? cfg.relayerServer.host;
48
+ await startRelayer(ctx, {
49
+ port,
50
+ host,
51
+ feedId,
52
+ });
53
+ }
54
+ catch (error) {
55
+ console.error("Start relayer failed:", error);
56
+ process.exit(1);
57
+ }
58
+ });
59
+ program.addCommand(relayerCommand);
60
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerSubstreamCommands(program: Command): void;