@5ive-tech/sdk 1.1.2

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 (119) hide show
  1. package/README.md +279 -0
  2. package/dist/FiveSDK.d.ts +336 -0
  3. package/dist/FiveSDK.js +395 -0
  4. package/dist/accounts/index.d.ts +254 -0
  5. package/dist/accounts/index.js +543 -0
  6. package/dist/assets/vm/dummy.file +0 -0
  7. package/dist/assets/vm/five_vm_wasm.d.ts +762 -0
  8. package/dist/assets/vm/five_vm_wasm.js +3754 -0
  9. package/dist/assets/vm/five_vm_wasm_bg.js +3307 -0
  10. package/dist/assets/vm/five_vm_wasm_bg.wasm +0 -0
  11. package/dist/assets/vm/five_vm_wasm_bg.wasm.d.ts +247 -0
  12. package/dist/assets/vm/package.json +11 -0
  13. package/dist/bin/gen-types.d.ts +2 -0
  14. package/dist/bin/gen-types.js +35 -0
  15. package/dist/compiler/BytecodeCompiler.d.ts +83 -0
  16. package/dist/compiler/BytecodeCompiler.js +379 -0
  17. package/dist/config/ConfigManager.d.ts +13 -0
  18. package/dist/config/ConfigManager.js +27 -0
  19. package/dist/config/ProgramIdResolver.d.ts +62 -0
  20. package/dist/config/ProgramIdResolver.js +104 -0
  21. package/dist/crypto/index.d.ts +211 -0
  22. package/dist/crypto/index.js +451 -0
  23. package/dist/encoding/ParameterEncoder.d.ts +31 -0
  24. package/dist/encoding/ParameterEncoder.js +278 -0
  25. package/dist/index.d.ts +21 -0
  26. package/dist/index.js +28 -0
  27. package/dist/lib/bytecode-encoder.d.ts +62 -0
  28. package/dist/lib/bytecode-encoder.js +281 -0
  29. package/dist/logging/index.d.ts +9 -0
  30. package/dist/logging/index.js +10 -0
  31. package/dist/metadata/index.d.ts +213 -0
  32. package/dist/metadata/index.js +296 -0
  33. package/dist/modules/accounts.d.ts +60 -0
  34. package/dist/modules/accounts.js +275 -0
  35. package/dist/modules/deploy.d.ts +90 -0
  36. package/dist/modules/deploy.js +1118 -0
  37. package/dist/modules/execute.d.ts +90 -0
  38. package/dist/modules/execute.js +649 -0
  39. package/dist/modules/fees.d.ts +14 -0
  40. package/dist/modules/fees.js +112 -0
  41. package/dist/modules/namespaces.d.ts +39 -0
  42. package/dist/modules/namespaces.js +190 -0
  43. package/dist/modules/state-diff.d.ts +35 -0
  44. package/dist/modules/state-diff.js +342 -0
  45. package/dist/modules/vm-state.d.ts +7 -0
  46. package/dist/modules/vm-state.js +44 -0
  47. package/dist/program/AccountResolver.d.ts +67 -0
  48. package/dist/program/AccountResolver.js +134 -0
  49. package/dist/program/BorshSchemaGenerator.d.ts +8 -0
  50. package/dist/program/BorshSchemaGenerator.js +57 -0
  51. package/dist/program/FiveProgram.d.ts +144 -0
  52. package/dist/program/FiveProgram.js +282 -0
  53. package/dist/program/FunctionBuilder.d.ts +114 -0
  54. package/dist/program/FunctionBuilder.js +347 -0
  55. package/dist/program/ProgramAccount.d.ts +38 -0
  56. package/dist/program/ProgramAccount.js +170 -0
  57. package/dist/program/TypeGenerator.d.ts +90 -0
  58. package/dist/program/TypeGenerator.js +195 -0
  59. package/dist/program/index.d.ts +24 -0
  60. package/dist/program/index.js +21 -0
  61. package/dist/project/config.d.ts +5 -0
  62. package/dist/project/config.js +33 -0
  63. package/dist/project/toml.d.ts +6 -0
  64. package/dist/project/toml.js +43 -0
  65. package/dist/project/workspace.d.ts +160 -0
  66. package/dist/project/workspace.js +73 -0
  67. package/dist/testing/AccountMetaGenerator.d.ts +121 -0
  68. package/dist/testing/AccountMetaGenerator.js +261 -0
  69. package/dist/testing/AccountTestFixture.d.ts +211 -0
  70. package/dist/testing/AccountTestFixture.js +530 -0
  71. package/dist/testing/OnChainAccountManager.d.ts +81 -0
  72. package/dist/testing/OnChainAccountManager.js +260 -0
  73. package/dist/testing/StateSerializer.d.ts +65 -0
  74. package/dist/testing/StateSerializer.js +330 -0
  75. package/dist/testing/TestDiscovery.d.ts +79 -0
  76. package/dist/testing/TestDiscovery.js +274 -0
  77. package/dist/testing/TestRunner.d.ts +117 -0
  78. package/dist/testing/TestRunner.js +346 -0
  79. package/dist/testing/index.d.ts +14 -0
  80. package/dist/testing/index.js +13 -0
  81. package/dist/types.d.ts +356 -0
  82. package/dist/types.js +32 -0
  83. package/dist/utils/abi.d.ts +31 -0
  84. package/dist/utils/abi.js +92 -0
  85. package/dist/utils/transaction.d.ts +5 -0
  86. package/dist/utils/transaction.js +48 -0
  87. package/dist/validation/InputValidator.d.ts +142 -0
  88. package/dist/validation/InputValidator.js +332 -0
  89. package/dist/validation/index.d.ts +4 -0
  90. package/dist/validation/index.js +4 -0
  91. package/dist/wasm/compiler/AbiLogic.d.ts +4 -0
  92. package/dist/wasm/compiler/AbiLogic.js +37 -0
  93. package/dist/wasm/compiler/AnalysisLogic.d.ts +6 -0
  94. package/dist/wasm/compiler/AnalysisLogic.js +61 -0
  95. package/dist/wasm/compiler/CompilationLogic.d.ts +10 -0
  96. package/dist/wasm/compiler/CompilationLogic.js +431 -0
  97. package/dist/wasm/compiler/FiveCompiler.d.ts +48 -0
  98. package/dist/wasm/compiler/FiveCompiler.js +183 -0
  99. package/dist/wasm/compiler/InfoLogic.d.ts +6 -0
  100. package/dist/wasm/compiler/InfoLogic.js +24 -0
  101. package/dist/wasm/compiler/OptimizationLogic.d.ts +2 -0
  102. package/dist/wasm/compiler/OptimizationLogic.js +13 -0
  103. package/dist/wasm/compiler/ValidationLogic.d.ts +7 -0
  104. package/dist/wasm/compiler/ValidationLogic.js +26 -0
  105. package/dist/wasm/compiler/index.d.ts +2 -0
  106. package/dist/wasm/compiler/index.js +2 -0
  107. package/dist/wasm/compiler/types.d.ts +8 -0
  108. package/dist/wasm/compiler/types.js +1 -0
  109. package/dist/wasm/compiler/utils.d.ts +8 -0
  110. package/dist/wasm/compiler/utils.js +75 -0
  111. package/dist/wasm/index.d.ts +9 -0
  112. package/dist/wasm/index.js +12 -0
  113. package/dist/wasm/instance.d.ts +1 -0
  114. package/dist/wasm/instance.js +26 -0
  115. package/dist/wasm/loader.d.ts +7 -0
  116. package/dist/wasm/loader.js +112 -0
  117. package/dist/wasm/vm.d.ts +33 -0
  118. package/dist/wasm/vm.js +250 -0
  119. package/package.json +59 -0
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Five Bytecode Compiler
3
+ *
4
+ * Handles compilation of Five script source (.v files) to bytecode (.bin files)
5
+ * using the existing WASM compilation infrastructure.
6
+ *
7
+ * This maintains the real compilation capabilities while providing a clean SDK interface.
8
+ */
9
+ import { readFile } from "fs/promises";
10
+ import { CompilationSDKError, } from "../types.js";
11
+ import { normalizeAbiFunctions } from "../utils/abi.js";
12
+ /**
13
+ * Bytecode compiler for Five scripts
14
+ */
15
+ export class BytecodeCompiler {
16
+ constructor(config = {}) {
17
+ this.debug = config.debug || false;
18
+ if (this.debug) {
19
+ console.log("[BytecodeCompiler] Initialized");
20
+ }
21
+ }
22
+ /**
23
+ * Compile Five script source to bytecode
24
+ */
25
+ async compile(source, options = {}) {
26
+ const startTime = Date.now();
27
+ const sourceContent = typeof source === 'string' ? source : source.content;
28
+ const sourceFilename = typeof source === 'string' ? 'unknown.v' : source.filename || 'unknown.v';
29
+ // Compile source (debug info available in this.debug mode)
30
+ try {
31
+ // Lazy load WASM compiler
32
+ if (!this.wasmCompiler) {
33
+ await this.loadWasmCompiler();
34
+ }
35
+ // Prepare compilation options - pass through all metrics options
36
+ const compilerOptions = {
37
+ optimize: options.optimize || false,
38
+ target: options.target || "vm",
39
+ debug: options.debug || false,
40
+ maxSize: options.maxSize || 1048576, // 1MB default
41
+ optimizationLevel: options.optimizationLevel || "production", // Default to Production
42
+ // Pass through metrics options
43
+ metricsFormat: options.metricsFormat,
44
+ metricsOutput: options.metricsOutput,
45
+ errorFormat: options.errorFormat,
46
+ includeMetrics: options.includeMetrics,
47
+ comprehensiveMetrics: options.comprehensiveMetrics,
48
+ };
49
+ // Perform compilation
50
+ const result = await this.wasmCompiler.compile(sourceContent, compilerOptions);
51
+ const compilationTime = Date.now() - startTime;
52
+ if (result.success && result.bytecode) {
53
+ let abiData = result.abi;
54
+ if (!abiData) {
55
+ abiData = await this.generateABI(source);
56
+ }
57
+ if (this.debug) {
58
+ console.log(`[BytecodeCompiler] Compilation successful in ${compilationTime}ms`);
59
+ console.log(`[BytecodeCompiler] Bytecode size: ${result.bytecode.length} bytes`);
60
+ }
61
+ const normalizedFunctions = normalizeAbiFunctions(abiData?.functions ?? abiData);
62
+ const normalizedAbi = {
63
+ ...abiData,
64
+ functions: normalizedFunctions,
65
+ };
66
+ const compilerInfo = await this.getCompilerInfo();
67
+ return {
68
+ success: true,
69
+ bytecode: result.bytecode,
70
+ abi: normalizedAbi,
71
+ disassembly: result.disassembly || [],
72
+ metadata: {
73
+ sourceFile: sourceFilename,
74
+ timestamp: new Date().toISOString(),
75
+ compilerVersion: compilerInfo.version || '1.0.0',
76
+ target: (options.target || 'vm'),
77
+ optimizations: [],
78
+ originalSize: sourceContent.length,
79
+ compressedSize: result.bytecode.length,
80
+ compressionRatio: 1.0,
81
+ sourceSize: sourceContent.length,
82
+ bytecodeSize: result.bytecode.length,
83
+ functions: this.extractFunctions(normalizedAbi),
84
+ compilationTime,
85
+ },
86
+ metricsReport: result.metricsReport,
87
+ };
88
+ }
89
+ else {
90
+ const errors = this.transformErrors(result.errors || []);
91
+ if (this.debug) {
92
+ console.log(`[BytecodeCompiler] Compilation failed with ${errors.length} errors`);
93
+ errors.forEach((error) => {
94
+ console.log(` - ${error.severity}: ${error.message} (${error.line}:${error.column})`);
95
+ });
96
+ }
97
+ return {
98
+ success: false,
99
+ errors,
100
+ metricsReport: result.metricsReport,
101
+ };
102
+ }
103
+ }
104
+ catch (error) {
105
+ throw new CompilationSDKError(`Compilation error: ${error instanceof Error ? error.message : "Unknown error"}`, { source: sourceContent.substring(0, 200), options });
106
+ }
107
+ }
108
+ /**
109
+ * Compile multiple modules (entry + dependencies)
110
+ */
111
+ async compileModules(mainSource, modules, options = {}) {
112
+ const startTime = Date.now();
113
+ try {
114
+ if (!this.wasmCompiler) {
115
+ await this.loadWasmCompiler();
116
+ }
117
+ if (!this.wasmCompiler?.compile_multi) {
118
+ throw new CompilationSDKError("Multi-file compilation is not supported in this build");
119
+ }
120
+ const compilerOptions = {
121
+ optimize: options.optimize || false,
122
+ target: options.target || "vm",
123
+ debug: options.debug || false,
124
+ maxSize: options.maxSize || 1048576,
125
+ optimizationLevel: options.optimizationLevel || "production",
126
+ includeMetrics: options.includeMetrics || options.metricsOutput !== undefined,
127
+ metricsFormat: options.metricsFormat || "json",
128
+ errorFormat: options.errorFormat || "terminal",
129
+ comprehensiveMetrics: options.comprehensiveMetrics || false,
130
+ };
131
+ const result = await this.wasmCompiler.compile_multi(mainSource.content, modules, compilerOptions);
132
+ const compilationTime = Date.now() - startTime;
133
+ if (result.success && result.bytecode) {
134
+ const compilerInfo = await this.getCompilerInfo();
135
+ return {
136
+ success: true,
137
+ bytecode: result.bytecode,
138
+ abi: result.abi,
139
+ disassembly: result.disassembly || [],
140
+ metadata: {
141
+ sourceFile: mainSource.filename || 'main.v',
142
+ timestamp: new Date().toISOString(),
143
+ compilerVersion: compilerInfo.version || '1.0.0',
144
+ target: (options.target || 'vm'),
145
+ optimizations: [],
146
+ originalSize: mainSource.content.length,
147
+ compressedSize: result.bytecode.length,
148
+ compressionRatio: 1.0,
149
+ sourceSize: mainSource.content.length,
150
+ bytecodeSize: result.bytecode.length,
151
+ functions: [],
152
+ compilationTime,
153
+ },
154
+ metricsReport: result.metricsReport,
155
+ };
156
+ }
157
+ else {
158
+ const errors = this.transformErrors(result.errors || result.compiler_errors || []);
159
+ return {
160
+ success: false,
161
+ errors,
162
+ metricsReport: result.metricsReport,
163
+ };
164
+ }
165
+ }
166
+ catch (error) {
167
+ throw new CompilationSDKError(`Compilation error: ${error instanceof Error ? error.message : "Unknown error"}`, { options });
168
+ }
169
+ }
170
+ /**
171
+ * Compile script from file path
172
+ */
173
+ async compileFile(filePath, options = {}) {
174
+ if (this.debug) {
175
+ console.log(`[BytecodeCompiler] Reading file: ${filePath}`);
176
+ }
177
+ try {
178
+ const source = await readFile(filePath, "utf-8");
179
+ return this.compile(source, options);
180
+ }
181
+ catch (error) {
182
+ throw new CompilationSDKError(`Failed to read file ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`, { filePath, options });
183
+ }
184
+ }
185
+ /**
186
+ * Validate Five script source without compiling
187
+ */
188
+ async validateSource(source) {
189
+ const code = typeof source === 'string' ? source : source.content;
190
+ if (this.debug) {
191
+ console.log(`[BytecodeCompiler] Validating source (${code.length} chars)...`);
192
+ }
193
+ try {
194
+ if (!this.wasmCompiler) {
195
+ await this.loadWasmCompiler();
196
+ }
197
+ const result = await this.wasmCompiler.validateSource(code);
198
+ return {
199
+ valid: result.valid,
200
+ errors: result.errors ? this.transformErrors(result.errors) : undefined,
201
+ };
202
+ }
203
+ catch (error) {
204
+ if (this.debug) {
205
+ console.log(`[BytecodeCompiler] Validation error: ${error}`);
206
+ }
207
+ return {
208
+ valid: false,
209
+ errors: [
210
+ {
211
+ message: error instanceof Error
212
+ ? error.message
213
+ : "Unknown validation error",
214
+ severity: "error",
215
+ },
216
+ ],
217
+ };
218
+ }
219
+ }
220
+ /**
221
+ * Get compiler version and information
222
+ */
223
+ async getCompilerInfo() {
224
+ try {
225
+ if (!this.wasmCompiler) {
226
+ await this.loadWasmCompiler();
227
+ }
228
+ let version = "1.0.0";
229
+ if (this.wasmCompiler && typeof this.wasmCompiler.getCompilerInfo === 'function') {
230
+ const info = this.wasmCompiler.getCompilerInfo();
231
+ version = info.version;
232
+ }
233
+ return {
234
+ version,
235
+ wasmLoaded: !!this.wasmCompiler,
236
+ debug: this.debug,
237
+ };
238
+ }
239
+ catch (error) {
240
+ return {
241
+ version: "unknown",
242
+ wasmLoaded: false,
243
+ debug: this.debug,
244
+ error: error instanceof Error ? error.message : "Unknown error",
245
+ };
246
+ }
247
+ }
248
+ // ==================== Private Methods ====================
249
+ /**
250
+ * Load WASM compiler (reuse existing infrastructure)
251
+ */
252
+ async loadWasmCompiler() {
253
+ try {
254
+ // Load WASM compiler silently unless debug
255
+ // Import existing WASM compiler from the SDK
256
+ const wasmModule = await import("../wasm/compiler/index.js");
257
+ const wasmInstance = new wasmModule.FiveCompiler(this.createWasmLogger());
258
+ // Initialize the compiler
259
+ await wasmInstance.initialize();
260
+ this.wasmCompiler = wasmInstance;
261
+ this.wasmModule = wasmModule;
262
+ if (this.debug) {
263
+ console.log("[BytecodeCompiler] WASM compiler loaded and initialized successfully");
264
+ }
265
+ }
266
+ catch (error) {
267
+ throw new CompilationSDKError(`Failed to load WASM compiler: ${error instanceof Error ? error.message : "Unknown error"}`, { debug: this.debug });
268
+ }
269
+ }
270
+ createWasmLogger() {
271
+ if (this.debug) {
272
+ return console;
273
+ }
274
+ return {
275
+ debug: () => { },
276
+ info: () => { },
277
+ warn: console.warn.bind(console),
278
+ error: console.error.bind(console),
279
+ };
280
+ }
281
+ /**
282
+ * Transform compiler errors to SDK format
283
+ */
284
+ transformErrors(errors) {
285
+ return errors.map((error) => ({
286
+ type: 'compiler',
287
+ message: error.message || error.toString(),
288
+ line: error.line,
289
+ column: error.column,
290
+ severity: error.severity || "error",
291
+ }));
292
+ }
293
+ /**
294
+ * Extract function definitions from ABI
295
+ */
296
+ extractFunctions(abi) {
297
+ const functions = normalizeAbiFunctions(abi?.functions ?? abi);
298
+ return functions.map((func) => ({
299
+ name: func.name,
300
+ index: func.index,
301
+ parameters: func.parameters?.map((param) => ({
302
+ name: param.name,
303
+ type: param.type,
304
+ optional: param.optional || false,
305
+ })) || [],
306
+ returnType: func.returnType,
307
+ }));
308
+ }
309
+ /**
310
+ * Generate ABI from Five script source code
311
+ */
312
+ async generateABI(source) {
313
+ const code = typeof source === 'string' ? source : source.content;
314
+ if (this.debug) {
315
+ console.log(`[BytecodeCompiler] Generating ABI for source (${code.length} chars)...`);
316
+ }
317
+ try {
318
+ if (!this.wasmCompiler) {
319
+ await this.loadWasmCompiler();
320
+ }
321
+ const abi = await this.wasmCompiler.generateABI(code);
322
+ const normalizedFunctions = normalizeAbiFunctions(abi?.functions ?? abi);
323
+ return { ...abi, functions: normalizedFunctions };
324
+ }
325
+ catch (error) {
326
+ if (this.debug) {
327
+ console.log(`[BytecodeCompiler] ABI generation error: ${error}`);
328
+ }
329
+ throw new CompilationSDKError(`ABI generation failed: ${error instanceof Error ? error.message : "Unknown error"}`, { source: code.substring(0, 100) });
330
+ }
331
+ }
332
+ /**
333
+ * Extract function names from compiled bytecode
334
+ */
335
+ async getFunctionNames(bytecode) {
336
+ if (this.debug) {
337
+ console.log(`[BytecodeCompiler] Extracting function names from bytecode (${bytecode.length} bytes)...`);
338
+ }
339
+ try {
340
+ if (!this.wasmCompiler) {
341
+ await this.loadWasmCompiler();
342
+ }
343
+ let namesJson = null;
344
+ if (this.wasmCompiler &&
345
+ typeof this.wasmCompiler.getFunctionNames === "function") {
346
+ namesJson = await this.wasmCompiler.getFunctionNames(bytecode);
347
+ }
348
+ else if (this.wasmModule &&
349
+ typeof this.wasmModule.get_function_names === "function") {
350
+ namesJson = await this.wasmModule.get_function_names(bytecode);
351
+ }
352
+ // Fallback: direct call if previous attempts yielded no data
353
+ if (!namesJson && this.wasmModule?.get_function_names) {
354
+ namesJson = this.wasmModule.get_function_names(bytecode);
355
+ }
356
+ let parsedNames = namesJson;
357
+ if (typeof namesJson === "string") {
358
+ try {
359
+ parsedNames = JSON.parse(namesJson);
360
+ }
361
+ catch (e) {
362
+ if (this.debug) {
363
+ console.log(`[BytecodeCompiler] Failed to parse function names JSON:`, e);
364
+ }
365
+ }
366
+ }
367
+ if (this.debug) {
368
+ console.log(`[BytecodeCompiler] Function names extracted: ${JSON.stringify(parsedNames)}`);
369
+ }
370
+ return parsedNames || [];
371
+ }
372
+ catch (error) {
373
+ if (this.debug) {
374
+ console.log(`[BytecodeCompiler] Function name extraction error: ${error}`);
375
+ }
376
+ throw new CompilationSDKError(`Function name extraction failed: ${error instanceof Error ? error.message : "Unknown error"}`, { bytecodeLength: bytecode.length });
377
+ }
378
+ }
379
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Five SDK configuration manager.
3
+ */
4
+ import { FiveSDKConfig } from '../types.js';
5
+ export declare class ConfigManager {
6
+ private static instance;
7
+ private config;
8
+ private constructor();
9
+ static getInstance(): ConfigManager;
10
+ get(): Promise<any>;
11
+ getSync(): any;
12
+ set(config: Partial<FiveSDKConfig>): Promise<void>;
13
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Five SDK configuration manager.
3
+ */
4
+ const DEFAULT_CONFIG = {
5
+ network: 'devnet',
6
+ debug: false
7
+ };
8
+ export class ConfigManager {
9
+ constructor() {
10
+ this.config = { ...DEFAULT_CONFIG };
11
+ }
12
+ static getInstance() {
13
+ if (!ConfigManager.instance) {
14
+ ConfigManager.instance = new ConfigManager();
15
+ }
16
+ return ConfigManager.instance;
17
+ }
18
+ async get() {
19
+ return this.config;
20
+ }
21
+ getSync() {
22
+ return this.config;
23
+ }
24
+ async set(config) {
25
+ this.config = { ...this.config, ...config };
26
+ }
27
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Centralized program ID resolution for Five SDK.
3
+ * Implements consistent precedence: explicit → default → env → baked → error
4
+ */
5
+ /**
6
+ * Baked program ID injected at release time (set by scripts/set-default-program-id.sh)
7
+ * Empty string by default; overridden in npm published packages.
8
+ */
9
+ export declare const FIVE_BAKED_PROGRAM_ID = "";
10
+ /**
11
+ * Centralized resolver for program IDs across all SDK operations.
12
+ * Ensures consistent validation and error messaging.
13
+ */
14
+ export declare class ProgramIdResolver {
15
+ private static defaultProgramId;
16
+ /**
17
+ * Set the default program ID for the entire SDK.
18
+ * Used when no explicit program ID is provided.
19
+ * @param programId - Solana public key (base58 encoded)
20
+ * @throws {ValidationError} - If programId is not a valid Solana address
21
+ */
22
+ static setDefault(programId: string): void;
23
+ /**
24
+ * Get the currently set default program ID.
25
+ * @returns The default program ID, or undefined if not set
26
+ */
27
+ static getDefault(): string | undefined;
28
+ /**
29
+ * Resolve program ID with consistent precedence.
30
+ * Order: explicit → instance default → env (FIVE_PROGRAM_ID) → baked → error
31
+ *
32
+ * @param explicit - Explicit program ID (highest priority)
33
+ * @param options - Resolution options
34
+ * @returns Resolved program ID (validated)
35
+ * @throws {Error} - If no valid program ID resolves and allowUndefined is false
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * // Will use explicit if provided, fall back through chain
40
+ * const programId = ProgramIdResolver.resolve(options.fiveVMProgramId);
41
+ *
42
+ * // For local/WASM paths that don't need program ID
43
+ * const optional = ProgramIdResolver.resolveOptional(options.fiveVMProgramId);
44
+ * ```
45
+ */
46
+ static resolve(explicit?: string, options?: {
47
+ allowUndefined?: boolean;
48
+ }): string;
49
+ /**
50
+ * Resolve program ID but allow undefined return.
51
+ * Used for local/WASM execution paths that don't require a program ID.
52
+ *
53
+ * @param explicit - Explicit program ID (highest priority)
54
+ * @returns Resolved program ID (validated) or undefined if no resolution possible
55
+ */
56
+ static resolveOptional(explicit?: string): string | undefined;
57
+ /**
58
+ * Clear the default program ID.
59
+ * Useful for testing or resetting to clean state.
60
+ */
61
+ static clearDefault(): void;
62
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Centralized program ID resolution for Five SDK.
3
+ * Implements consistent precedence: explicit → default → env → baked → error
4
+ */
5
+ import { validator } from '../validation/index.js';
6
+ /**
7
+ * Baked program ID injected at release time (set by scripts/set-default-program-id.sh)
8
+ * Empty string by default; overridden in npm published packages.
9
+ */
10
+ export const FIVE_BAKED_PROGRAM_ID = '';
11
+ /**
12
+ * Centralized resolver for program IDs across all SDK operations.
13
+ * Ensures consistent validation and error messaging.
14
+ */
15
+ export class ProgramIdResolver {
16
+ /**
17
+ * Set the default program ID for the entire SDK.
18
+ * Used when no explicit program ID is provided.
19
+ * @param programId - Solana public key (base58 encoded)
20
+ * @throws {ValidationError} - If programId is not a valid Solana address
21
+ */
22
+ static setDefault(programId) {
23
+ validator.validateBase58Address(programId, 'defaultProgramId');
24
+ this.defaultProgramId = programId;
25
+ }
26
+ /**
27
+ * Get the currently set default program ID.
28
+ * @returns The default program ID, or undefined if not set
29
+ */
30
+ static getDefault() {
31
+ return this.defaultProgramId;
32
+ }
33
+ /**
34
+ * Resolve program ID with consistent precedence.
35
+ * Order: explicit → instance default → env (FIVE_PROGRAM_ID) → baked → error
36
+ *
37
+ * @param explicit - Explicit program ID (highest priority)
38
+ * @param options - Resolution options
39
+ * @returns Resolved program ID (validated)
40
+ * @throws {Error} - If no valid program ID resolves and allowUndefined is false
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * // Will use explicit if provided, fall back through chain
45
+ * const programId = ProgramIdResolver.resolve(options.fiveVMProgramId);
46
+ *
47
+ * // For local/WASM paths that don't need program ID
48
+ * const optional = ProgramIdResolver.resolveOptional(options.fiveVMProgramId);
49
+ * ```
50
+ */
51
+ static resolve(explicit, options) {
52
+ // Precedence: explicit → default → env → baked
53
+ // Note: Must check for explicit empty string differently from undefined
54
+ let resolved;
55
+ if (explicit) {
56
+ resolved = explicit;
57
+ }
58
+ else if (this.defaultProgramId) {
59
+ resolved = this.defaultProgramId;
60
+ }
61
+ else if (process.env.FIVE_PROGRAM_ID) {
62
+ resolved = process.env.FIVE_PROGRAM_ID;
63
+ }
64
+ else if (FIVE_BAKED_PROGRAM_ID) {
65
+ resolved = FIVE_BAKED_PROGRAM_ID;
66
+ }
67
+ if (!resolved && !options?.allowUndefined) {
68
+ throw new Error(`No program ID resolved for Five VM. ` +
69
+ `Set via one of: ` +
70
+ `(1) explicit call parameter, ` +
71
+ `(2) FiveSDK.setDefaultProgramId(), ` +
72
+ `(3) FIVE_PROGRAM_ID environment variable, ` +
73
+ `(4) released package default. ` +
74
+ `For setup guidance, see: https://docs.five.build/cli/program-id-setup`);
75
+ }
76
+ if (resolved) {
77
+ validator.validateBase58Address(resolved, 'programId');
78
+ }
79
+ return resolved || '';
80
+ }
81
+ /**
82
+ * Resolve program ID but allow undefined return.
83
+ * Used for local/WASM execution paths that don't require a program ID.
84
+ *
85
+ * @param explicit - Explicit program ID (highest priority)
86
+ * @returns Resolved program ID (validated) or undefined if no resolution possible
87
+ */
88
+ static resolveOptional(explicit) {
89
+ try {
90
+ const result = this.resolve(explicit, { allowUndefined: true });
91
+ return result || undefined;
92
+ }
93
+ catch {
94
+ return undefined;
95
+ }
96
+ }
97
+ /**
98
+ * Clear the default program ID.
99
+ * Useful for testing or resetting to clean state.
100
+ */
101
+ static clearDefault() {
102
+ this.defaultProgramId = undefined;
103
+ }
104
+ }