@5ive-tech/sdk 1.1.10 → 1.1.13
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.
- package/README.md +1 -1
- package/dist/FiveSDK.d.ts +3 -4
- package/dist/FiveSDK.js +47 -5
- package/dist/accounts/index.js +3 -2
- package/dist/assets/vm/five_vm_wasm_bg.wasm +0 -0
- package/dist/assets/vm/five_vm_wasm_bg.wasm.d.ts +5 -5
- package/dist/bin/gen-types.js +0 -0
- package/dist/compiler/BytecodeCompiler.d.ts +1 -7
- package/dist/compiler/BytecodeCompiler.js +105 -44
- package/dist/config/ProgramIdResolver.d.ts +1 -6
- package/dist/config/ProgramIdResolver.js +11 -16
- package/dist/config/VmClusterConfigResolver.d.ts +27 -0
- package/dist/config/VmClusterConfigResolver.js +111 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/modules/accounts.js +7 -1
- package/dist/modules/admin.js +25 -12
- package/dist/modules/deploy.js +62 -23
- package/dist/modules/execute.js +71 -37
- package/dist/modules/vm-state.js +6 -1
- package/dist/program/FunctionBuilder.d.ts +8 -0
- package/dist/program/FunctionBuilder.js +18 -5
- package/dist/project/config.js +0 -1
- package/dist/testing/TestRunner.js +6 -1
- package/dist/types.d.ts +19 -2
- package/dist/utils/abi.d.ts +4 -0
- package/dist/utils/abi.js +3 -0
- package/dist/utils/transaction.d.ts +22 -0
- package/dist/utils/transaction.js +94 -12
- package/dist/wasm/compiler/CompilationLogic.d.ts +0 -5
- package/dist/wasm/compiler/CompilationLogic.js +45 -163
- package/dist/wasm/compiler/FiveCompiler.d.ts +0 -5
- package/dist/wasm/compiler/FiveCompiler.js +0 -6
- package/dist/wasm/compiler/utils.d.ts +34 -1
- package/dist/wasm/compiler/utils.js +223 -5
- package/package.json +4 -3
package/README.md
CHANGED
package/dist/FiveSDK.d.ts
CHANGED
|
@@ -98,10 +98,7 @@ export declare class FiveSDK {
|
|
|
98
98
|
static compile(source: FiveScriptSource | string, options?: CompilationOptions & {
|
|
99
99
|
debug?: boolean;
|
|
100
100
|
}): Promise<CompilationResult>;
|
|
101
|
-
static
|
|
102
|
-
name: string;
|
|
103
|
-
source: string;
|
|
104
|
-
}>, options?: CompilationOptions & {
|
|
101
|
+
static compileProject(projectPath?: string, options?: CompilationOptions & {
|
|
105
102
|
debug?: boolean;
|
|
106
103
|
}): Promise<CompilationResult>;
|
|
107
104
|
static compileWithDiscovery(entryPoint: string, options?: CompilationOptions & {
|
|
@@ -175,6 +172,8 @@ export declare class FiveSDK {
|
|
|
175
172
|
isWritable: boolean;
|
|
176
173
|
isSystemAccount?: boolean;
|
|
177
174
|
}>;
|
|
175
|
+
feeShardIndex?: number;
|
|
176
|
+
payerAccount?: string;
|
|
178
177
|
}): Promise<SerializedExecution>;
|
|
179
178
|
static getVMState(connection: any, fiveVMProgramId?: string): Promise<{
|
|
180
179
|
authority: string;
|
package/dist/FiveSDK.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Five SDK client for Five VM scripts.
|
|
3
3
|
*/
|
|
4
|
+
import { dirname, isAbsolute, join, resolve, } from "path";
|
|
5
|
+
import { readFile, } from "fs/promises";
|
|
4
6
|
import { FiveSDKError, } from "./types.js";
|
|
5
7
|
import { BytecodeCompiler } from "./compiler/BytecodeCompiler.js";
|
|
6
8
|
import { ParameterEncoder } from "./encoding/ParameterEncoder.js";
|
|
@@ -16,6 +18,8 @@ import * as Accounts from "./modules/accounts.js";
|
|
|
16
18
|
import * as StateDiff from "./modules/state-diff.js";
|
|
17
19
|
import * as Namespaces from "./modules/namespaces.js";
|
|
18
20
|
import * as Admin from "./modules/admin.js";
|
|
21
|
+
import { parseToml } from "./project/toml.js";
|
|
22
|
+
import { parseProjectConfig } from "./project/config.js";
|
|
19
23
|
/**
|
|
20
24
|
* Main Five SDK class - entry point for all Five VM interactions
|
|
21
25
|
*/
|
|
@@ -130,7 +134,11 @@ export class FiveSDK {
|
|
|
130
134
|
parameters: func.parameters?.map((param) => ({
|
|
131
135
|
name: param.name,
|
|
132
136
|
type: param.type,
|
|
137
|
+
param_type: param.param_type,
|
|
133
138
|
optional: param.optional ?? false,
|
|
139
|
+
is_account: param.is_account ?? param.isAccount ?? false,
|
|
140
|
+
isAccount: param.isAccount ?? param.is_account ?? false,
|
|
141
|
+
attributes: Array.isArray(param.attributes) ? [...param.attributes] : [],
|
|
134
142
|
})) || [],
|
|
135
143
|
returnType: func.returnType,
|
|
136
144
|
}));
|
|
@@ -155,16 +163,50 @@ export class FiveSDK {
|
|
|
155
163
|
return result;
|
|
156
164
|
}
|
|
157
165
|
catch (error) {
|
|
158
|
-
|
|
166
|
+
if (error instanceof FiveSDKError) {
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
const inheritedDetails = error && typeof error === "object" && error.details
|
|
170
|
+
? error.details
|
|
171
|
+
: undefined;
|
|
172
|
+
throw new FiveSDKError(`Compilation failed: ${error instanceof Error ? error.message : "Unknown error"}`, "COMPILATION_ERROR", {
|
|
173
|
+
...(inheritedDetails || {}),
|
|
174
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
175
|
+
});
|
|
159
176
|
}
|
|
160
177
|
}
|
|
161
|
-
static async
|
|
162
|
-
const mainSourceObj = typeof mainSource === 'string' ? { content: mainSource, filename: 'main.v' } : mainSource;
|
|
178
|
+
static async compileProject(projectPath = process.cwd(), options = {}) {
|
|
163
179
|
Validators.options(options);
|
|
164
180
|
await this.initializeComponents(options.debug);
|
|
165
|
-
if (!this.compiler)
|
|
181
|
+
if (!this.compiler) {
|
|
166
182
|
throw new FiveSDKError("Compiler not initialized", "COMPILER_ERROR");
|
|
167
|
-
|
|
183
|
+
}
|
|
184
|
+
const normalizedProjectPath = isAbsolute(projectPath)
|
|
185
|
+
? projectPath
|
|
186
|
+
: resolve(process.cwd(), projectPath);
|
|
187
|
+
const configPath = normalizedProjectPath.endsWith(".toml")
|
|
188
|
+
? normalizedProjectPath
|
|
189
|
+
: join(normalizedProjectPath, "five.toml");
|
|
190
|
+
const rootDir = dirname(configPath);
|
|
191
|
+
const rawToml = await readFile(configPath, "utf8");
|
|
192
|
+
const parsed = parseToml(rawToml);
|
|
193
|
+
const projectConfig = parseProjectConfig(parsed);
|
|
194
|
+
if (!projectConfig.entryPoint) {
|
|
195
|
+
throw new FiveSDKError(`Missing required project.entry_point in ${configPath}`, "PROJECT_CONFIG_ERROR");
|
|
196
|
+
}
|
|
197
|
+
const entryPoint = isAbsolute(projectConfig.entryPoint)
|
|
198
|
+
? projectConfig.entryPoint
|
|
199
|
+
: resolve(rootDir, projectConfig.entryPoint);
|
|
200
|
+
return this.compiler.compileWithDiscovery(entryPoint, {
|
|
201
|
+
...options,
|
|
202
|
+
target: options.target || projectConfig.target || "vm",
|
|
203
|
+
optimizationLevel: options.optimizationLevel ||
|
|
204
|
+
projectConfig.optimizations?.optimizationLevel ||
|
|
205
|
+
"production",
|
|
206
|
+
includeMetrics: options.includeMetrics,
|
|
207
|
+
metricsFormat: options.metricsFormat || "json",
|
|
208
|
+
errorFormat: options.errorFormat || "terminal",
|
|
209
|
+
});
|
|
168
210
|
}
|
|
169
211
|
static async compileWithDiscovery(entryPoint, options = {}) {
|
|
170
212
|
Validators.options(options);
|
package/dist/accounts/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* and account size calculations. Uses serialization instead of direct blockchain calls.
|
|
6
6
|
*/
|
|
7
7
|
import { PDAUtils, SolanaPublicKeyUtils, RentCalculator, AccountValidator } from '../crypto/index.js';
|
|
8
|
+
import { ProgramIdResolver } from '../config/ProgramIdResolver.js';
|
|
8
9
|
/**
|
|
9
10
|
* AccountType enum for test compatibility
|
|
10
11
|
*/
|
|
@@ -22,8 +23,8 @@ export const AccountType = {
|
|
|
22
23
|
* Account manager for Five VM scripts (serialization-based)
|
|
23
24
|
*/
|
|
24
25
|
export class FiveAccountManager {
|
|
25
|
-
constructor(programId
|
|
26
|
-
this.programId = programId;
|
|
26
|
+
constructor(programId) {
|
|
27
|
+
this.programId = ProgramIdResolver.resolve(programId);
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
30
|
* Encode System Program CreateAccount instruction
|
|
Binary file
|
|
@@ -227,19 +227,19 @@ export const bytecodeencoder_encoded_size_u32: (a: number) => number;
|
|
|
227
227
|
export const bytecodeencoder_encoded_size_u16: (a: number) => number;
|
|
228
228
|
export const parameterencoder_encode_execute: (a: number, b: number, c: number) => void;
|
|
229
229
|
export const get_wasm_compiler_info: () => number;
|
|
230
|
+
export const __wbg_set_wasmsuggestion_confidence: (a: number, b: number) => void;
|
|
231
|
+
export const __wbg_set_wasmenhancedcompilationresult_compilation_time: (a: number, b: number) => void;
|
|
232
|
+
export const __wbg_set_wasmcompilationwithmetrics_compilation_time: (a: number, b: number) => void;
|
|
233
|
+
export const __wbg_set_wasmcompilationresult_compilation_time: (a: number, b: number) => void;
|
|
230
234
|
export const __wbg_get_wasmsuggestion_confidence: (a: number) => number;
|
|
231
235
|
export const __wbg_get_wasmenhancedcompilationresult_compilation_time: (a: number) => number;
|
|
232
236
|
export const __wbg_get_wasmcompilationwithmetrics_compilation_time: (a: number) => number;
|
|
233
237
|
export const __wbg_get_wasmcompilationresult_compilation_time: (a: number) => number;
|
|
234
238
|
export const __wbg_set_wasmenhancedcompilationresult_success: (a: number, b: number) => void;
|
|
235
239
|
export const __wbg_get_wasmenhancedcompilationresult_success: (a: number) => number;
|
|
236
|
-
export const __wbg_set_wasmsuggestion_confidence: (a: number, b: number) => void;
|
|
237
|
-
export const __wbg_set_wasmenhancedcompilationresult_compilation_time: (a: number, b: number) => void;
|
|
238
|
-
export const __wbg_set_wasmcompilationwithmetrics_compilation_time: (a: number, b: number) => void;
|
|
239
|
-
export const __wbg_set_wasmcompilationresult_compilation_time: (a: number, b: number) => void;
|
|
240
240
|
export const __wbg_wasmfivecompiler_free: (a: number, b: number) => void;
|
|
241
|
-
export const __wbg_parameterencoder_free: (a: number, b: number) => void;
|
|
242
241
|
export const __wbg_bytecodeencoder_free: (a: number, b: number) => void;
|
|
242
|
+
export const __wbg_parameterencoder_free: (a: number, b: number) => void;
|
|
243
243
|
export const __wbindgen_export: (a: number, b: number) => number;
|
|
244
244
|
export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
245
245
|
export const __wbindgen_export3: (a: number) => void;
|
package/dist/bin/gen-types.js
CHANGED
|
File without changes
|
|
@@ -26,13 +26,7 @@ export declare class BytecodeCompiler {
|
|
|
26
26
|
* Compile Five script source to bytecode
|
|
27
27
|
*/
|
|
28
28
|
compile(source: FiveScriptSource | string, options?: CompilationOptions): Promise<CompilationResult>;
|
|
29
|
-
|
|
30
|
-
* Compile multiple modules (entry + dependencies)
|
|
31
|
-
*/
|
|
32
|
-
compileModules(mainSource: FiveScriptSource, modules: Array<{
|
|
33
|
-
name: string;
|
|
34
|
-
source: string;
|
|
35
|
-
}>, options?: CompilationOptions): Promise<CompilationResult>;
|
|
29
|
+
compileWithDiscovery(entryPoint: string, options?: CompilationOptions): Promise<CompilationResult>;
|
|
36
30
|
/**
|
|
37
31
|
* Compile script from file path
|
|
38
32
|
*/
|
|
@@ -39,6 +39,7 @@ export class BytecodeCompiler {
|
|
|
39
39
|
debug: options.debug || false,
|
|
40
40
|
maxSize: options.maxSize || 1048576, // 1MB default
|
|
41
41
|
optimizationLevel: options.optimizationLevel || "production", // Default to Production
|
|
42
|
+
sourceFile: sourceFilename,
|
|
42
43
|
// Pass through metrics options
|
|
43
44
|
metricsFormat: options.metricsFormat,
|
|
44
45
|
metricsOutput: options.metricsOutput,
|
|
@@ -87,7 +88,7 @@ export class BytecodeCompiler {
|
|
|
87
88
|
};
|
|
88
89
|
}
|
|
89
90
|
else {
|
|
90
|
-
const errors = this.transformErrors(result.errors || []);
|
|
91
|
+
const errors = this.transformErrors(result.diagnostics || result.errors || []);
|
|
91
92
|
if (this.debug) {
|
|
92
93
|
console.log(`[BytecodeCompiler] Compilation failed with ${errors.length} errors`);
|
|
93
94
|
errors.forEach((error) => {
|
|
@@ -97,74 +98,96 @@ export class BytecodeCompiler {
|
|
|
97
98
|
return {
|
|
98
99
|
success: false,
|
|
99
100
|
errors,
|
|
101
|
+
diagnostics: errors,
|
|
102
|
+
formattedErrorsTerminal: result.formattedErrorsTerminal,
|
|
103
|
+
formattedErrorsJson: result.formattedErrorsJson,
|
|
100
104
|
metricsReport: result.metricsReport,
|
|
101
105
|
};
|
|
102
106
|
}
|
|
103
107
|
}
|
|
104
108
|
catch (error) {
|
|
105
|
-
|
|
109
|
+
if (error instanceof CompilationSDKError) {
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
const inheritedDetails = error && typeof error === "object" && error.details
|
|
113
|
+
? error.details
|
|
114
|
+
: undefined;
|
|
115
|
+
throw new CompilationSDKError(`Compilation error: ${error instanceof Error ? error.message : "Unknown error"}`, {
|
|
116
|
+
...(inheritedDetails || {}),
|
|
117
|
+
source: sourceContent.substring(0, 200),
|
|
118
|
+
options,
|
|
119
|
+
});
|
|
106
120
|
}
|
|
107
121
|
}
|
|
108
|
-
|
|
109
|
-
* Compile multiple modules (entry + dependencies)
|
|
110
|
-
*/
|
|
111
|
-
async compileModules(mainSource, modules, options = {}) {
|
|
122
|
+
async compileWithDiscovery(entryPoint, options = {}) {
|
|
112
123
|
const startTime = Date.now();
|
|
113
124
|
try {
|
|
114
125
|
if (!this.wasmCompiler) {
|
|
115
126
|
await this.loadWasmCompiler();
|
|
116
127
|
}
|
|
117
|
-
if (!this.wasmCompiler?.
|
|
118
|
-
throw new CompilationSDKError("
|
|
128
|
+
if (!this.wasmCompiler?.compileWithDiscovery) {
|
|
129
|
+
throw new CompilationSDKError("Compiler discovery API is not supported in this build");
|
|
119
130
|
}
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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);
|
|
131
|
+
const result = await this.wasmCompiler.compileWithDiscovery(entryPoint, {
|
|
132
|
+
...options,
|
|
133
|
+
sourceFile: entryPoint,
|
|
134
|
+
});
|
|
132
135
|
const compilationTime = Date.now() - startTime;
|
|
133
136
|
if (result.success && result.bytecode) {
|
|
134
137
|
const compilerInfo = await this.getCompilerInfo();
|
|
138
|
+
let abiData = result.abi;
|
|
139
|
+
if (!abiData) {
|
|
140
|
+
abiData = await this.generateABI(typeof entryPoint === 'string' ? await readFile(entryPoint, 'utf8') : entryPoint);
|
|
141
|
+
}
|
|
142
|
+
const normalizedFunctions = normalizeAbiFunctions(abiData?.functions ?? abiData);
|
|
143
|
+
const normalizedAbi = {
|
|
144
|
+
...abiData,
|
|
145
|
+
functions: normalizedFunctions,
|
|
146
|
+
};
|
|
135
147
|
return {
|
|
136
148
|
success: true,
|
|
137
149
|
bytecode: result.bytecode,
|
|
138
|
-
abi:
|
|
150
|
+
abi: normalizedAbi,
|
|
139
151
|
disassembly: result.disassembly || [],
|
|
140
152
|
metadata: {
|
|
141
|
-
sourceFile:
|
|
153
|
+
sourceFile: entryPoint,
|
|
142
154
|
timestamp: new Date().toISOString(),
|
|
143
|
-
compilerVersion: compilerInfo.version ||
|
|
144
|
-
target: (options.target ||
|
|
155
|
+
compilerVersion: compilerInfo.version || "1.0.0",
|
|
156
|
+
target: (options.target || "vm"),
|
|
145
157
|
optimizations: [],
|
|
146
|
-
originalSize:
|
|
158
|
+
originalSize: 0,
|
|
147
159
|
compressedSize: result.bytecode.length,
|
|
148
160
|
compressionRatio: 1.0,
|
|
149
|
-
sourceSize:
|
|
161
|
+
sourceSize: 0,
|
|
150
162
|
bytecodeSize: result.bytecode.length,
|
|
151
|
-
functions:
|
|
163
|
+
functions: this.extractFunctions(normalizedAbi),
|
|
152
164
|
compilationTime,
|
|
153
165
|
},
|
|
154
166
|
metricsReport: result.metricsReport,
|
|
155
167
|
};
|
|
156
168
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
169
|
+
const errors = this.transformErrors(result.diagnostics || result.errors || []);
|
|
170
|
+
return {
|
|
171
|
+
success: false,
|
|
172
|
+
errors,
|
|
173
|
+
diagnostics: errors,
|
|
174
|
+
formattedErrorsTerminal: result.formattedErrorsTerminal,
|
|
175
|
+
formattedErrorsJson: result.formattedErrorsJson,
|
|
176
|
+
metricsReport: result.metricsReport,
|
|
177
|
+
};
|
|
165
178
|
}
|
|
166
179
|
catch (error) {
|
|
167
|
-
|
|
180
|
+
if (error instanceof CompilationSDKError) {
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
const inheritedDetails = error && typeof error === "object" && error.details
|
|
184
|
+
? error.details
|
|
185
|
+
: undefined;
|
|
186
|
+
throw new CompilationSDKError(`Compilation error: ${error instanceof Error ? error.message : "Unknown error"}`, {
|
|
187
|
+
...(inheritedDetails || {}),
|
|
188
|
+
entryPoint,
|
|
189
|
+
options,
|
|
190
|
+
});
|
|
168
191
|
}
|
|
169
192
|
}
|
|
170
193
|
/**
|
|
@@ -176,7 +199,13 @@ export class BytecodeCompiler {
|
|
|
176
199
|
}
|
|
177
200
|
try {
|
|
178
201
|
const source = await readFile(filePath, "utf-8");
|
|
179
|
-
return this.compile(
|
|
202
|
+
return this.compile({
|
|
203
|
+
filename: filePath,
|
|
204
|
+
content: source,
|
|
205
|
+
}, {
|
|
206
|
+
...options,
|
|
207
|
+
sourceFile: filePath,
|
|
208
|
+
});
|
|
180
209
|
}
|
|
181
210
|
catch (error) {
|
|
182
211
|
throw new CompilationSDKError(`Failed to read file ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`, { filePath, options });
|
|
@@ -282,13 +311,45 @@ export class BytecodeCompiler {
|
|
|
282
311
|
* Transform compiler errors to SDK format
|
|
283
312
|
*/
|
|
284
313
|
transformErrors(errors) {
|
|
285
|
-
return errors.map((error) =>
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
line
|
|
289
|
-
column
|
|
290
|
-
|
|
291
|
-
|
|
314
|
+
return errors.map((error) => {
|
|
315
|
+
const normalized = typeof error === "string" ? { message: error } : (error || {});
|
|
316
|
+
const location = normalized.location || {};
|
|
317
|
+
const lineValue = normalized.line ?? location.line;
|
|
318
|
+
const columnValue = normalized.column ?? location.column;
|
|
319
|
+
const line = typeof lineValue === "number"
|
|
320
|
+
? lineValue
|
|
321
|
+
: typeof lineValue === "string"
|
|
322
|
+
? Number(lineValue)
|
|
323
|
+
: undefined;
|
|
324
|
+
const column = typeof columnValue === "number"
|
|
325
|
+
? columnValue
|
|
326
|
+
: typeof columnValue === "string"
|
|
327
|
+
? Number(columnValue)
|
|
328
|
+
: undefined;
|
|
329
|
+
return {
|
|
330
|
+
type: normalized.type || "compiler",
|
|
331
|
+
message: normalized.message || String(error),
|
|
332
|
+
line: Number.isFinite(line) ? line : undefined,
|
|
333
|
+
column: Number.isFinite(column) ? column : undefined,
|
|
334
|
+
severity: normalized.severity || "error",
|
|
335
|
+
code: normalized.code,
|
|
336
|
+
category: normalized.category,
|
|
337
|
+
description: normalized.description,
|
|
338
|
+
location: normalized.location,
|
|
339
|
+
sourceLocation: normalized.sourceLocation || location.file,
|
|
340
|
+
suggestion: normalized.suggestion ||
|
|
341
|
+
(Array.isArray(normalized.suggestions) && normalized.suggestions.length > 0
|
|
342
|
+
? typeof normalized.suggestions[0] === "string"
|
|
343
|
+
? normalized.suggestions[0]
|
|
344
|
+
: normalized.suggestions[0]?.message
|
|
345
|
+
: undefined),
|
|
346
|
+
suggestions: normalized.suggestions,
|
|
347
|
+
sourceLine: normalized.sourceLine || normalized.source_line,
|
|
348
|
+
sourceSnippet: normalized.sourceSnippet || normalized.source_snippet,
|
|
349
|
+
rendered: normalized.rendered,
|
|
350
|
+
raw: normalized.raw || error,
|
|
351
|
+
};
|
|
352
|
+
});
|
|
292
353
|
}
|
|
293
354
|
/**
|
|
294
355
|
* Extract function definitions from ABI
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Centralized program ID resolution for Five SDK.
|
|
3
|
-
* Implements
|
|
3
|
+
* Implements strict precedence: explicit → SDK default → cluster config → error
|
|
4
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 = "4Qxf3pbCse2veUgZVMiAm3nWqJrYo2pT4suxHKMJdK1d";
|
|
10
5
|
/**
|
|
11
6
|
* Centralized resolver for program IDs across all SDK operations.
|
|
12
7
|
* Ensures consistent validation and error messaging.
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Centralized program ID resolution for Five SDK.
|
|
3
|
-
* Implements
|
|
3
|
+
* Implements strict precedence: explicit → SDK default → cluster config → error
|
|
4
4
|
*/
|
|
5
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 = '4Qxf3pbCse2veUgZVMiAm3nWqJrYo2pT4suxHKMJdK1d';
|
|
6
|
+
import { VmClusterConfigResolver } from './VmClusterConfigResolver.js';
|
|
11
7
|
/**
|
|
12
8
|
* Centralized resolver for program IDs across all SDK operations.
|
|
13
9
|
* Ensures consistent validation and error messaging.
|
|
@@ -49,8 +45,7 @@ export class ProgramIdResolver {
|
|
|
49
45
|
* ```
|
|
50
46
|
*/
|
|
51
47
|
static resolve(explicit, options) {
|
|
52
|
-
// Precedence: explicit → default →
|
|
53
|
-
// Note: Must check for explicit empty string differently from undefined
|
|
48
|
+
// Precedence: explicit → default → cluster-config
|
|
54
49
|
let resolved;
|
|
55
50
|
if (explicit) {
|
|
56
51
|
resolved = explicit;
|
|
@@ -58,20 +53,20 @@ export class ProgramIdResolver {
|
|
|
58
53
|
else if (this.defaultProgramId) {
|
|
59
54
|
resolved = this.defaultProgramId;
|
|
60
55
|
}
|
|
61
|
-
else
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
56
|
+
else {
|
|
57
|
+
try {
|
|
58
|
+
resolved = VmClusterConfigResolver.loadClusterConfig().programId;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
resolved = undefined;
|
|
62
|
+
}
|
|
66
63
|
}
|
|
67
64
|
if (!resolved && !options?.allowUndefined) {
|
|
68
65
|
throw new Error(`No program ID resolved for Five VM. ` +
|
|
69
66
|
`Set via one of: ` +
|
|
70
67
|
`(1) explicit call parameter, ` +
|
|
71
68
|
`(2) FiveSDK.setDefaultProgramId(), ` +
|
|
72
|
-
`(3)
|
|
73
|
-
`(4) released package default. ` +
|
|
74
|
-
`For setup guidance, see: https://docs.five.build/cli/program-id-setup`);
|
|
69
|
+
`(3) five-solana/constants.vm.toml cluster profile.`);
|
|
75
70
|
}
|
|
76
71
|
if (resolved) {
|
|
77
72
|
validator.validateBase58Address(resolved, 'programId');
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface VmClusterProfile {
|
|
2
|
+
cluster: 'localnet' | 'devnet' | 'mainnet';
|
|
3
|
+
configPath: string;
|
|
4
|
+
programId: string;
|
|
5
|
+
feeVaultShardCount: number;
|
|
6
|
+
}
|
|
7
|
+
export interface VmClusterAddresses {
|
|
8
|
+
cluster: VmClusterProfile['cluster'];
|
|
9
|
+
programId: string;
|
|
10
|
+
feeVaultShardCount: number;
|
|
11
|
+
vmStatePda: string;
|
|
12
|
+
vmStateBump: number;
|
|
13
|
+
feeVaultPdas: Array<{
|
|
14
|
+
shardIndex: number;
|
|
15
|
+
address: string;
|
|
16
|
+
bump: number;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
export declare class VmClusterConfigResolver {
|
|
20
|
+
static resolveClusterFromEnvOrDefault(): VmClusterProfile['cluster'];
|
|
21
|
+
static getDefaultConfigPath(): string;
|
|
22
|
+
static loadClusterConfig(input?: {
|
|
23
|
+
cluster?: string;
|
|
24
|
+
configPath?: string;
|
|
25
|
+
}): VmClusterProfile;
|
|
26
|
+
static deriveVmAddresses(profile: VmClusterProfile): VmClusterAddresses;
|
|
27
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { PublicKey } from '@solana/web3.js';
|
|
4
|
+
const VM_STATE_SEED = Buffer.from('vm_state', 'utf-8');
|
|
5
|
+
const FEE_VAULT_SEED = Buffer.from([
|
|
6
|
+
0xff, 0x66, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x6d, 0x5f, 0x66, 0x65, 0x65,
|
|
7
|
+
0x5f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x31,
|
|
8
|
+
]);
|
|
9
|
+
const VALID_CLUSTERS = new Set(['localnet', 'devnet', 'mainnet']);
|
|
10
|
+
function resolveDefaultConfigPath() {
|
|
11
|
+
if (process.env.FIVE_VM_CONSTANTS_CONFIG) {
|
|
12
|
+
return path.resolve(process.env.FIVE_VM_CONSTANTS_CONFIG);
|
|
13
|
+
}
|
|
14
|
+
const candidates = [
|
|
15
|
+
path.resolve(process.cwd(), 'five-solana/constants.vm.toml'),
|
|
16
|
+
path.resolve(process.cwd(), '../five-solana/constants.vm.toml'),
|
|
17
|
+
];
|
|
18
|
+
for (const candidate of candidates) {
|
|
19
|
+
if (fs.existsSync(candidate)) {
|
|
20
|
+
return candidate;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return candidates[0];
|
|
24
|
+
}
|
|
25
|
+
function parseSimpleVmToml(raw) {
|
|
26
|
+
const clusters = {};
|
|
27
|
+
let current = null;
|
|
28
|
+
for (const lineRaw of raw.split('\n')) {
|
|
29
|
+
const line = lineRaw.trim();
|
|
30
|
+
if (!line || line.startsWith('#'))
|
|
31
|
+
continue;
|
|
32
|
+
const sec = line.match(/^\[clusters\.(localnet|devnet|mainnet)\]$/);
|
|
33
|
+
if (sec) {
|
|
34
|
+
current = sec[1];
|
|
35
|
+
clusters[current] = {};
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (!current)
|
|
39
|
+
continue;
|
|
40
|
+
const kv = line.match(/^([a-z_]+)\s*=\s*(.+)$/);
|
|
41
|
+
if (!kv)
|
|
42
|
+
continue;
|
|
43
|
+
const key = kv[1];
|
|
44
|
+
const rawVal = kv[2].trim();
|
|
45
|
+
if (rawVal.startsWith('"') && rawVal.endsWith('"')) {
|
|
46
|
+
clusters[current][key] = rawVal.slice(1, -1);
|
|
47
|
+
}
|
|
48
|
+
else if (/^\d+$/.test(rawVal)) {
|
|
49
|
+
clusters[current][key] = Number(rawVal);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
throw new Error(`Unsupported TOML value: ${line}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return { clusters };
|
|
56
|
+
}
|
|
57
|
+
export class VmClusterConfigResolver {
|
|
58
|
+
static resolveClusterFromEnvOrDefault() {
|
|
59
|
+
const cluster = (process.env.FIVE_VM_CLUSTER || 'localnet').trim();
|
|
60
|
+
if (!VALID_CLUSTERS.has(cluster)) {
|
|
61
|
+
throw new Error(`Invalid FIVE_VM_CLUSTER: ${cluster} (expected localnet|devnet|mainnet)`);
|
|
62
|
+
}
|
|
63
|
+
return cluster;
|
|
64
|
+
}
|
|
65
|
+
static getDefaultConfigPath() {
|
|
66
|
+
return resolveDefaultConfigPath();
|
|
67
|
+
}
|
|
68
|
+
static loadClusterConfig(input = {}) {
|
|
69
|
+
const cluster = (input.cluster || this.resolveClusterFromEnvOrDefault()).trim();
|
|
70
|
+
if (!VALID_CLUSTERS.has(cluster)) {
|
|
71
|
+
throw new Error(`Invalid cluster: ${cluster}`);
|
|
72
|
+
}
|
|
73
|
+
const configPath = path.resolve(input.configPath || this.getDefaultConfigPath());
|
|
74
|
+
if (!fs.existsSync(configPath)) {
|
|
75
|
+
throw new Error(`VM constants config not found: ${configPath}`);
|
|
76
|
+
}
|
|
77
|
+
const parsed = parseSimpleVmToml(fs.readFileSync(configPath, 'utf-8'));
|
|
78
|
+
const entry = parsed.clusters?.[cluster];
|
|
79
|
+
if (!entry)
|
|
80
|
+
throw new Error(`Cluster missing in VM constants config: ${cluster}`);
|
|
81
|
+
if (!entry.program_id)
|
|
82
|
+
throw new Error(`Missing program_id for cluster ${cluster}`);
|
|
83
|
+
if (!Number.isInteger(entry.fee_vault_shard_count) || entry.fee_vault_shard_count < 1) {
|
|
84
|
+
throw new Error(`Invalid fee_vault_shard_count for cluster ${cluster}`);
|
|
85
|
+
}
|
|
86
|
+
const programId = new PublicKey(entry.program_id).toBase58();
|
|
87
|
+
return {
|
|
88
|
+
cluster: cluster,
|
|
89
|
+
configPath,
|
|
90
|
+
programId,
|
|
91
|
+
feeVaultShardCount: entry.fee_vault_shard_count,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
static deriveVmAddresses(profile) {
|
|
95
|
+
const programPk = new PublicKey(profile.programId);
|
|
96
|
+
const [vmStatePda, vmStateBump] = PublicKey.findProgramAddressSync([VM_STATE_SEED], programPk);
|
|
97
|
+
const feeVaultPdas = [];
|
|
98
|
+
for (let i = 0; i < profile.feeVaultShardCount; i++) {
|
|
99
|
+
const [vault, bump] = PublicKey.findProgramAddressSync([FEE_VAULT_SEED, Buffer.from([i])], programPk);
|
|
100
|
+
feeVaultPdas.push({ shardIndex: i, address: vault.toBase58(), bump });
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
cluster: profile.cluster,
|
|
104
|
+
programId: profile.programId,
|
|
105
|
+
feeVaultShardCount: profile.feeVaultShardCount,
|
|
106
|
+
vmStatePda: vmStatePda.toBase58(),
|
|
107
|
+
vmStateBump,
|
|
108
|
+
feeVaultPdas,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -17,5 +17,5 @@ export * from './wasm/loader.js';
|
|
|
17
17
|
export * from './testing/index.js';
|
|
18
18
|
export * from './program/index.js';
|
|
19
19
|
export * from './modules/namespaces.js';
|
|
20
|
-
export { ProgramIdResolver
|
|
20
|
+
export { ProgramIdResolver } from './config/ProgramIdResolver.js';
|
|
21
21
|
export { FIVE_VM_PROGRAM_ID } from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ export * from './testing/index.js';
|
|
|
21
21
|
export * from './program/index.js';
|
|
22
22
|
export * from './modules/namespaces.js';
|
|
23
23
|
// ==================== Program ID Resolution ====================
|
|
24
|
-
export { ProgramIdResolver
|
|
24
|
+
export { ProgramIdResolver } from './config/ProgramIdResolver.js';
|
|
25
25
|
// ==================== Constants ====================
|
|
26
26
|
export { FIVE_VM_PROGRAM_ID } from './types.js';
|
|
27
27
|
// Default export disabled for minimal build
|
package/dist/modules/accounts.js
CHANGED
|
@@ -2,6 +2,7 @@ import { ScriptMetadataParser } from "../metadata/index.js";
|
|
|
2
2
|
import { normalizeAbiFunctions } from "../utils/abi.js";
|
|
3
3
|
import { loadWasmVM } from "../wasm/instance.js";
|
|
4
4
|
import { SolanaPublicKeyUtils } from "../crypto/index.js";
|
|
5
|
+
import { getAccountInfoWithRetry } from "../utils/transaction.js";
|
|
5
6
|
export async function fetchAccountAndDeserialize(accountAddress, connection, // Solana Connection object
|
|
6
7
|
options = {}) {
|
|
7
8
|
try {
|
|
@@ -27,7 +28,12 @@ options = {}) {
|
|
|
27
28
|
logs: [],
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
|
-
const accountInfo = await connection
|
|
31
|
+
const accountInfo = await getAccountInfoWithRetry(connection, accountPubkey, {
|
|
32
|
+
commitment: "finalized",
|
|
33
|
+
retries: 2,
|
|
34
|
+
delayMs: 1000,
|
|
35
|
+
debug: options.debug,
|
|
36
|
+
});
|
|
31
37
|
if (!accountInfo) {
|
|
32
38
|
return {
|
|
33
39
|
success: false,
|