@5ive-tech/sdk 1.1.10 → 1.1.12
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 +1 -4
- package/dist/FiveSDK.js +47 -5
- package/dist/accounts/index.js +3 -2
- package/dist/assets/vm/dummy.file +0 -0
- package/dist/assets/vm/five_vm_wasm_bg.js +3307 -0
- 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/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 +55 -21
- package/dist/modules/execute.js +58 -32
- package/dist/modules/vm-state.js +6 -1
- 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
|
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;
|
|
@@ -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,
|
package/dist/modules/admin.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { validator } from "../validation/index.js";
|
|
2
2
|
import { ProgramIdResolver } from "../config/ProgramIdResolver.js";
|
|
3
|
+
import { confirmTransactionRobust } from "../utils/transaction.js";
|
|
3
4
|
import bs58 from "bs58";
|
|
4
5
|
const VM_STATE_SEED = Buffer.from("vm_state", "utf8");
|
|
5
6
|
const FEE_VAULT_NAMESPACE_SEED = Buffer.from([
|
|
@@ -205,9 +206,12 @@ export async function initializeVmStateOnSolana(connection, authorityKeypair, op
|
|
|
205
206
|
preflightCommitment: "confirmed",
|
|
206
207
|
maxRetries: options.maxRetries || 3,
|
|
207
208
|
});
|
|
208
|
-
const confirmation = await connection
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
const confirmation = await confirmTransactionRobust(connection, signature, {
|
|
210
|
+
commitment: "finalized",
|
|
211
|
+
timeoutMs: 120000,
|
|
212
|
+
});
|
|
213
|
+
if (!confirmation.success) {
|
|
214
|
+
return { success: false, transactionId: signature, vmStateAccount: generated.vmStateAccount, error: confirmation.error || "confirmation failed" };
|
|
211
215
|
}
|
|
212
216
|
return { success: true, transactionId: signature, vmStateAccount: generated.vmStateAccount };
|
|
213
217
|
}
|
|
@@ -235,9 +239,12 @@ export async function setFeesOnSolana(connection, authorityKeypair, deployFeeLam
|
|
|
235
239
|
preflightCommitment: "confirmed",
|
|
236
240
|
maxRetries: options.maxRetries || 3,
|
|
237
241
|
});
|
|
238
|
-
const confirmation = await connection
|
|
239
|
-
|
|
240
|
-
|
|
242
|
+
const confirmation = await confirmTransactionRobust(connection, signature, {
|
|
243
|
+
commitment: "finalized",
|
|
244
|
+
timeoutMs: 120000,
|
|
245
|
+
});
|
|
246
|
+
if (!confirmation.success) {
|
|
247
|
+
return { success: false, transactionId: signature, vmStateAccount: generated.vmStateAccount, error: confirmation.error || "confirmation failed" };
|
|
241
248
|
}
|
|
242
249
|
return { success: true, transactionId: signature, vmStateAccount: generated.vmStateAccount };
|
|
243
250
|
}
|
|
@@ -266,14 +273,17 @@ export async function initFeeVaultOnSolana(connection, payerKeypair, shardIndex,
|
|
|
266
273
|
preflightCommitment: "confirmed",
|
|
267
274
|
maxRetries: options.maxRetries || 3,
|
|
268
275
|
});
|
|
269
|
-
const confirmation = await connection
|
|
270
|
-
|
|
276
|
+
const confirmation = await confirmTransactionRobust(connection, signature, {
|
|
277
|
+
commitment: "finalized",
|
|
278
|
+
timeoutMs: 120000,
|
|
279
|
+
});
|
|
280
|
+
if (!confirmation.success) {
|
|
271
281
|
return {
|
|
272
282
|
success: false,
|
|
273
283
|
transactionId: signature,
|
|
274
284
|
vmStateAccount: generated.vmStateAccount,
|
|
275
285
|
feeVaultAccount: generated.feeVaultAccount,
|
|
276
|
-
error:
|
|
286
|
+
error: confirmation.error || "confirmation failed",
|
|
277
287
|
};
|
|
278
288
|
}
|
|
279
289
|
return {
|
|
@@ -308,14 +318,17 @@ export async function withdrawScriptFeesOnSolana(connection, authorityKeypair, r
|
|
|
308
318
|
preflightCommitment: "confirmed",
|
|
309
319
|
maxRetries: options.maxRetries || 3,
|
|
310
320
|
});
|
|
311
|
-
const confirmation = await connection
|
|
312
|
-
|
|
321
|
+
const confirmation = await confirmTransactionRobust(connection, signature, {
|
|
322
|
+
commitment: "finalized",
|
|
323
|
+
timeoutMs: 120000,
|
|
324
|
+
});
|
|
325
|
+
if (!confirmation.success) {
|
|
313
326
|
return {
|
|
314
327
|
success: false,
|
|
315
328
|
transactionId: signature,
|
|
316
329
|
vmStateAccount: generated.vmStateAccount,
|
|
317
330
|
feeVaultAccount: generated.feeVaultAccount,
|
|
318
|
-
error:
|
|
331
|
+
error: confirmation.error || "confirmation failed",
|
|
319
332
|
};
|
|
320
333
|
}
|
|
321
334
|
return {
|