@5ive-tech/sdk 1.1.13 → 1.1.15

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 (44) hide show
  1. package/README.md +22 -0
  2. package/dist/FiveSDK.d.ts +43 -1
  3. package/dist/FiveSDK.js +6 -0
  4. package/dist/accounts/index.d.ts +10 -28
  5. package/dist/accounts/index.js +33 -61
  6. package/dist/assets/vm/five_vm_wasm.d.ts +8 -0
  7. package/dist/assets/vm/five_vm_wasm.js +25 -0
  8. package/dist/assets/vm/five_vm_wasm_bg.wasm +0 -0
  9. package/dist/assets/vm/five_vm_wasm_bg.wasm.d.ts +3 -0
  10. package/dist/bin/gen-types.js +0 -0
  11. package/dist/compiler/BytecodeCompiler.js +10 -6
  12. package/dist/compiler/source-normalization.d.ts +1 -0
  13. package/dist/compiler/source-normalization.js +67 -0
  14. package/dist/config/ProgramIdResolver.js +6 -2
  15. package/dist/constants/headers.d.ts +2 -0
  16. package/dist/constants/headers.js +2 -0
  17. package/dist/crypto/index.d.ts +8 -1
  18. package/dist/crypto/index.js +27 -14
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +1 -0
  21. package/dist/modules/accounts.js +1 -1
  22. package/dist/modules/deploy.js +167 -98
  23. package/dist/modules/execute.d.ts +5 -0
  24. package/dist/modules/execute.js +109 -50
  25. package/dist/modules/fees.js +2 -2
  26. package/dist/modules/namespaces.d.ts +11 -0
  27. package/dist/modules/namespaces.js +64 -0
  28. package/dist/program/FiveProgram.js +4 -3
  29. package/dist/program/TypeGenerator.js +8 -1
  30. package/dist/project/config.js +113 -1
  31. package/dist/project/workspace.d.ts +5 -0
  32. package/dist/testing/AccountTestFixture.js +3 -3
  33. package/dist/testing/TestDiscovery.d.ts +1 -0
  34. package/dist/testing/TestDiscovery.js +18 -2
  35. package/dist/testing/TestRunner.js +4 -1
  36. package/dist/types.d.ts +17 -6
  37. package/dist/types.js +2 -1
  38. package/dist/utils/abi.js +33 -10
  39. package/dist/utils/transaction.d.ts +16 -0
  40. package/dist/utils/transaction.js +81 -5
  41. package/dist/wasm/compiler/CompilationLogic.js +3 -3
  42. package/dist/wasm/vm.d.ts +2 -2
  43. package/dist/wasm/vm.js +10 -11
  44. package/package.json +1 -1
package/README.md CHANGED
@@ -2,12 +2,34 @@
2
2
 
3
3
  Client-agnostic TypeScript SDK for interacting with 5ive DSL programs on Solana.
4
4
 
5
+ ## Mainnet Program ID
6
+
7
+ **Program**: `5ive58PJUPaTyAe7tvU1bvBi25o7oieLLTRsJDoQNJst`
8
+
9
+ The Five VM is deployed and running on Solana mainnet. Use this program ID for production applications.
10
+
5
11
  ## Install
6
12
 
7
13
  ```bash
8
14
  npm install @5ive-tech/sdk @solana/web3.js
9
15
  ```
10
16
 
17
+ ## Localnet Validator Integration Test
18
+
19
+ The localnet integration suite is intentionally environment-gated. Before running:
20
+
21
+ 1. Rebuild the localnet SBF artifact:
22
+ - `./scripts/build-five-solana-cluster.sh --cluster localnet`
23
+ 2. Start a local validator and deploy the rebuilt localnet-compatible program.
24
+ 3. Export the deployed VM program id:
25
+ - `export FIVE_VM_PROGRAM_ID=<local-program-id>`
26
+
27
+ Then run:
28
+
29
+ ```bash
30
+ npm run test:localnet
31
+ ```
32
+
11
33
  ## Quick Start
12
34
 
13
35
  ### 1) Compile to `.five`
package/dist/FiveSDK.d.ts CHANGED
@@ -5,6 +5,25 @@ import { FiveSDKConfig, FiveScriptSource, FiveBytecode, CompilationOptions, Comp
5
5
  import { ScriptMetadata } from "./metadata/index.js";
6
6
  import * as Namespaces from "./modules/namespaces.js";
7
7
  import * as Admin from "./modules/admin.js";
8
+ export type ExecuteAccountMetadata = Map<string, {
9
+ isSigner: boolean;
10
+ isWritable: boolean;
11
+ isSystemAccount?: boolean;
12
+ }>;
13
+ export interface ExecuteOnSolanaOptions {
14
+ debug?: boolean;
15
+ network?: string;
16
+ computeUnitLimit?: number;
17
+ computeUnitPrice?: number;
18
+ maxRetries?: number;
19
+ skipPreflight?: boolean;
20
+ vmStateAccount?: string;
21
+ fiveVMProgramId?: string;
22
+ abi?: any;
23
+ accountMetadata?: ExecuteAccountMetadata;
24
+ feeShardIndex?: number;
25
+ payerAccount?: string;
26
+ }
8
27
  /**
9
28
  * Main Five SDK class - entry point for all Five VM interactions
10
29
  */
@@ -95,6 +114,29 @@ export declare class FiveSDK {
95
114
  resolvedScript?: string;
96
115
  bindingAddress: string;
97
116
  }>;
117
+ static setNamespaceSymbolPriceOnChain(symbol: string, priceLamports: number, options: {
118
+ managerScriptAccount: string;
119
+ connection: any;
120
+ signerKeypair: any;
121
+ fiveVMProgramId?: string;
122
+ debug?: boolean;
123
+ }): Promise<{
124
+ transactionId?: string;
125
+ symbol: Namespaces.ScopedNamespace["symbol"];
126
+ priceLamports: number;
127
+ }>;
128
+ static getNamespaceSymbolPriceOnChain(symbol: string, options: {
129
+ managerScriptAccount: string;
130
+ connection: any;
131
+ signerKeypair: any;
132
+ fiveVMProgramId?: string;
133
+ debug?: boolean;
134
+ }): Promise<{
135
+ transactionId?: string;
136
+ symbol: Namespaces.ScopedNamespace["symbol"];
137
+ priceLamports: number;
138
+ priceSol: number;
139
+ }>;
98
140
  static compile(source: FiveScriptSource | string, options?: CompilationOptions & {
99
141
  debug?: boolean;
100
142
  }): Promise<CompilationResult>;
@@ -209,7 +251,7 @@ export declare class FiveSDK {
209
251
  static getCachedScriptMetadata(scriptAccount: string, connection: any, cacheTTL?: number): Promise<ScriptMetadata>;
210
252
  static invalidateMetadataCache(scriptAccount: string): void;
211
253
  static getMetadataCacheStats(): any;
212
- static executeOnSolana(scriptAccount: string, connection: any, signerKeypair: any, functionName: string | number, parameters?: any[], accounts?: string[], options?: any): Promise<{
254
+ static executeOnSolana(scriptAccount: string, connection: any, signerKeypair: any, functionName: string | number, parameters?: any[], accounts?: string[], options?: ExecuteOnSolanaOptions): Promise<{
213
255
  success: boolean;
214
256
  result?: any;
215
257
  transactionId?: string;
package/dist/FiveSDK.js CHANGED
@@ -105,6 +105,12 @@ export class FiveSDK {
105
105
  static async resolveNamespaceOnChain(namespaceValue, options) {
106
106
  return Namespaces.resolveNamespaceOnChain(namespaceValue, options);
107
107
  }
108
+ static async setNamespaceSymbolPriceOnChain(symbol, priceLamports, options) {
109
+ return Namespaces.setNamespaceSymbolPriceOnChain(symbol, priceLamports, options);
110
+ }
111
+ static async getNamespaceSymbolPriceOnChain(symbol, options) {
112
+ return Namespaces.getNamespaceSymbolPriceOnChain(symbol, options);
113
+ }
108
114
  // ==================== Script Compilation ====================
109
115
  static async compile(source, options = {}) {
110
116
  const sourceContent = typeof source === 'string' ? source : source.content;
@@ -105,19 +105,14 @@ export interface AccountValidationResult {
105
105
  /**
106
106
  * Account creation parameters
107
107
  */
108
- export interface CreateAccountParams {
109
- /** Account size in bytes */
110
- size: number;
111
- /** Owner program ID */
112
- owner: string;
113
- /** Whether to make rent-exempt */
114
- rentExempt: boolean;
115
- /** Additional lamports beyond rent exemption */
116
- additionalLamports?: number;
108
+ export interface ProvisioningPlan {
109
+ address: string;
110
+ bump: number;
111
+ rentLamports: number;
112
+ creationMode: 'program_init_required';
113
+ ownerProgramId: string;
114
+ createInstruction: null;
117
115
  }
118
- /**
119
- * Solana transaction instruction interface
120
- */
121
116
  export interface TransactionInstruction {
122
117
  /** Program ID to invoke */
123
118
  programId: string;
@@ -136,10 +131,7 @@ export interface TransactionInstruction {
136
131
  export declare class FiveAccountManager {
137
132
  private programId;
138
133
  constructor(programId?: string);
139
- /**
140
- * Encode System Program CreateAccount instruction
141
- */
142
- private encodeCreateAccountInstruction;
134
+ private serializeInstruction;
143
135
  /**
144
136
  * Create script account PDA and return serialized instruction
145
137
  */
@@ -152,21 +144,11 @@ export declare class FiveAccountManager {
152
144
  /**
153
145
  * Create metadata account for script
154
146
  */
155
- createMetadataAccount(scriptAccount: string, payerAddress: string): Promise<{
156
- address: string;
157
- bump: number;
158
- createInstruction: TransactionInstruction;
159
- rentLamports: number;
160
- }>;
147
+ createMetadataAccount(scriptAccount: string, _payerAddress: string): Promise<ProvisioningPlan>;
161
148
  /**
162
149
  * Create user state account for script interaction
163
150
  */
164
- createUserStateAccount(userPublicKey: string, scriptAccount: string): Promise<{
165
- address: string;
166
- bump: number;
167
- createInstruction: any;
168
- rentLamports: number;
169
- }>;
151
+ createUserStateAccount(userPublicKey: string, scriptAccount: string): Promise<ProvisioningPlan>;
170
152
  /**
171
153
  * Validate account constraints for script execution
172
154
  */
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { PDAUtils, SolanaPublicKeyUtils, RentCalculator, AccountValidator } from '../crypto/index.js';
8
8
  import { ProgramIdResolver } from '../config/ProgramIdResolver.js';
9
+ import { PublicKey, SystemProgram } from '@solana/web3.js';
9
10
  /**
10
11
  * AccountType enum for test compatibility
11
12
  */
@@ -26,44 +27,35 @@ export class FiveAccountManager {
26
27
  constructor(programId) {
27
28
  this.programId = ProgramIdResolver.resolve(programId);
28
29
  }
29
- /**
30
- * Encode System Program CreateAccount instruction
31
- */
32
- encodeCreateAccountInstruction(params) {
33
- // Encoding for CreateAccount instruction
34
- // In a real implementation, this would use proper Solana instruction encoding
35
- const buffer = new ArrayBuffer(32);
36
- const view = new DataView(buffer);
37
- // Instruction discriminator for CreateAccount (0)
38
- view.setUint32(0, 0, true);
39
- // Account size
40
- view.setUint32(4, params.size, true);
41
- // Rent lamports (calculated)
42
- const rentLamports = params.rentExempt ? RentCalculator.calculateRentExemption(params.size) : 0;
43
- view.setBigUint64(8, BigInt(rentLamports), true);
44
- // Owner program ID would be encoded here in real implementation
45
- // Return the basic instruction data
46
- return new Uint8Array(buffer);
30
+ serializeInstruction(instruction) {
31
+ return {
32
+ programId: instruction.programId.toBase58(),
33
+ accounts: instruction.keys.map((key) => ({
34
+ pubkey: key.pubkey.toBase58(),
35
+ isSigner: key.isSigner,
36
+ isWritable: key.isWritable,
37
+ })),
38
+ data: new Uint8Array(instruction.data),
39
+ };
47
40
  }
48
41
  /**
49
42
  * Create script account PDA and return serialized instruction
50
43
  */
51
44
  async createScriptAccount(bytecode, payerAddress) {
52
- const pda = await PDAUtils.deriveScriptAccount(bytecode, this.programId);
45
+ const pda = await PDAUtils.deriveScriptAccount(bytecode, payerAddress, this.programId);
53
46
  const rentLamports = RentCalculator.getScriptAccountRent(bytecode.length);
54
- // Create serialized instruction for System Program CreateAccount
55
- const createInstruction = {
56
- programId: '11111111111111111111111111111112', // System Program
57
- accounts: [
58
- { pubkey: payerAddress, isSigner: true, isWritable: true },
59
- { pubkey: pda.address, isSigner: false, isWritable: true }
60
- ],
61
- data: this.encodeCreateAccountInstruction({
62
- size: bytecode.length + 256, // Bytecode + metadata
63
- owner: this.programId,
64
- rentExempt: true
65
- })
66
- };
47
+ const payerPubkey = new PublicKey(payerAddress);
48
+ const scriptPubkey = new PublicKey(pda.address);
49
+ const programPubkey = new PublicKey(this.programId);
50
+ const createInstruction = this.serializeInstruction(SystemProgram.createAccountWithSeed({
51
+ fromPubkey: payerPubkey,
52
+ newAccountPubkey: scriptPubkey,
53
+ basePubkey: payerPubkey,
54
+ seed: pda.seed,
55
+ lamports: rentLamports,
56
+ space: bytecode.length + 256,
57
+ programId: programPubkey,
58
+ }));
67
59
  return {
68
60
  address: pda.address,
69
61
  bump: pda.bump,
@@ -74,26 +66,16 @@ export class FiveAccountManager {
74
66
  /**
75
67
  * Create metadata account for script
76
68
  */
77
- async createMetadataAccount(scriptAccount, payerAddress) {
69
+ async createMetadataAccount(scriptAccount, _payerAddress) {
78
70
  const pda = await PDAUtils.deriveMetadataAccount(scriptAccount, this.programId);
79
71
  const rentLamports = RentCalculator.getMetadataAccountRent();
80
- const createInstruction = {
81
- programId: '11111111111111111111111111111112', // System Program
82
- accounts: [
83
- { pubkey: payerAddress, isSigner: true, isWritable: true },
84
- { pubkey: pda.address, isSigner: false, isWritable: true }
85
- ],
86
- data: this.encodeCreateAccountInstruction({
87
- size: 1024, // 1KB for metadata
88
- owner: this.programId,
89
- rentExempt: true
90
- })
91
- };
92
72
  return {
93
73
  address: pda.address,
94
74
  bump: pda.bump,
95
- createInstruction,
96
- rentLamports
75
+ rentLamports,
76
+ creationMode: 'program_init_required',
77
+ ownerProgramId: this.programId,
78
+ createInstruction: null,
97
79
  };
98
80
  }
99
81
  /**
@@ -105,20 +87,10 @@ export class FiveAccountManager {
105
87
  return {
106
88
  address: pda.address,
107
89
  bump: pda.bump,
108
- createInstruction: {
109
- programId: '11111111111111111111111111111112', // System Program
110
- accounts: [
111
- { pubkey: pda.address, isSigner: false, isWritable: true },
112
- { pubkey: userPublicKey, isSigner: true, isWritable: true },
113
- { pubkey: this.programId, isSigner: false, isWritable: false }
114
- ],
115
- data: this.encodeCreateAccountInstruction({
116
- size: 512, // 512 bytes for user state
117
- owner: this.programId,
118
- rentExempt: true
119
- })
120
- },
121
- rentLamports
90
+ rentLamports,
91
+ creationMode: 'program_init_required',
92
+ ownerProgramId: this.programId,
93
+ createInstruction: null,
122
94
  };
123
95
  }
124
96
  /**
@@ -280,6 +280,10 @@ export class WasmCompilationOptions {
280
280
  * Enable or disable debug information
281
281
  */
282
282
  with_debug_info(enabled: boolean): WasmCompilationOptions;
283
+ /**
284
+ * Enable or disable REQUIRE_BATCH lowering.
285
+ */
286
+ with_disable_require_batch(enabled: boolean): WasmCompilationOptions;
283
287
  /**
284
288
  * Enable or disable enhanced error reporting
285
289
  */
@@ -348,6 +352,10 @@ export class WasmCompilationOptions {
348
352
  * Enable bytecode compression
349
353
  */
350
354
  compress_output: boolean;
355
+ /**
356
+ * Disable REQUIRE_BATCH lowering in compiler pipeline.
357
+ */
358
+ disable_require_batch: boolean;
351
359
  /**
352
360
  * Enable constraint caching optimization
353
361
  */
@@ -924,6 +924,14 @@ class WasmCompilationOptions {
924
924
  const ret = wasm.__wbg_get_wasmcompilationoptions_compress_output(this.__wbg_ptr);
925
925
  return ret !== 0;
926
926
  }
927
+ /**
928
+ * Disable REQUIRE_BATCH lowering in compiler pipeline.
929
+ * @returns {boolean}
930
+ */
931
+ get disable_require_batch() {
932
+ const ret = wasm.__wbg_get_wasmcompilationoptions_disable_require_batch(this.__wbg_ptr);
933
+ return ret !== 0;
934
+ }
927
935
  /**
928
936
  * Enable constraint caching optimization
929
937
  * @returns {boolean}
@@ -1025,6 +1033,13 @@ class WasmCompilationOptions {
1025
1033
  set compress_output(arg0) {
1026
1034
  wasm.__wbg_set_wasmcompilationoptions_compress_output(this.__wbg_ptr, arg0);
1027
1035
  }
1036
+ /**
1037
+ * Disable REQUIRE_BATCH lowering in compiler pipeline.
1038
+ * @param {boolean} arg0
1039
+ */
1040
+ set disable_require_batch(arg0) {
1041
+ wasm.__wbg_set_wasmcompilationoptions_disable_require_batch(this.__wbg_ptr, arg0);
1042
+ }
1028
1043
  /**
1029
1044
  * Enable constraint caching optimization
1030
1045
  * @param {boolean} arg0
@@ -1323,6 +1338,16 @@ class WasmCompilationOptions {
1323
1338
  const ret = wasm.wasmcompilationoptions_with_debug_info(ptr, enabled);
1324
1339
  return WasmCompilationOptions.__wrap(ret);
1325
1340
  }
1341
+ /**
1342
+ * Enable or disable REQUIRE_BATCH lowering.
1343
+ * @param {boolean} enabled
1344
+ * @returns {WasmCompilationOptions}
1345
+ */
1346
+ with_disable_require_batch(enabled) {
1347
+ const ptr = this.__destroy_into_raw();
1348
+ const ret = wasm.wasmcompilationoptions_with_disable_require_batch(ptr, enabled);
1349
+ return WasmCompilationOptions.__wrap(ret);
1350
+ }
1326
1351
  /**
1327
1352
  * Enable or disable enhanced error reporting
1328
1353
  * @param {boolean} enabled
Binary file
@@ -116,6 +116,8 @@ export const __wbg_get_wasmcompilationoptions_compress_output: (a: number) => nu
116
116
  export const __wbg_set_wasmcompilationoptions_compress_output: (a: number, b: number) => void;
117
117
  export const __wbg_get_wasmcompilationoptions_enable_module_namespaces: (a: number) => number;
118
118
  export const __wbg_set_wasmcompilationoptions_enable_module_namespaces: (a: number, b: number) => void;
119
+ export const __wbg_get_wasmcompilationoptions_disable_require_batch: (a: number) => number;
120
+ export const __wbg_set_wasmcompilationoptions_disable_require_batch: (a: number, b: number) => void;
119
121
  export const wasmcompilationoptions_new: () => number;
120
122
  export const wasmcompilationoptions_with_mode: (a: number, b: number, c: number) => number;
121
123
  export const wasmcompilationoptions_with_optimization_level: (a: number, b: number, c: number) => number;
@@ -137,6 +139,7 @@ export const wasmcompilationoptions_with_export_format: (a: number, b: number, c
137
139
  export const wasmcompilationoptions_with_debug_info: (a: number, b: number) => number;
138
140
  export const wasmcompilationoptions_with_compression: (a: number, b: number) => number;
139
141
  export const wasmcompilationoptions_with_module_namespaces: (a: number, b: number) => number;
142
+ export const wasmcompilationoptions_with_disable_require_batch: (a: number, b: number) => number;
140
143
  export const wasmcompilationoptions_production_optimized: () => number;
141
144
  export const wasmcompilationoptions_development_debug: () => number;
142
145
  export const wasmcompilationoptions_fast_iteration: () => number;
File without changes
@@ -9,6 +9,7 @@
9
9
  import { readFile } from "fs/promises";
10
10
  import { CompilationSDKError, } from "../types.js";
11
11
  import { normalizeAbiFunctions } from "../utils/abi.js";
12
+ import { normalizeWasmCompilerSource } from "./source-normalization.js";
12
13
  /**
13
14
  * Bytecode compiler for Five scripts
14
15
  */
@@ -25,6 +26,7 @@ export class BytecodeCompiler {
25
26
  async compile(source, options = {}) {
26
27
  const startTime = Date.now();
27
28
  const sourceContent = typeof source === 'string' ? source : source.content;
29
+ const normalizedSourceContent = normalizeWasmCompilerSource(sourceContent);
28
30
  const sourceFilename = typeof source === 'string' ? 'unknown.v' : source.filename || 'unknown.v';
29
31
  // Compile source (debug info available in this.debug mode)
30
32
  try {
@@ -38,7 +40,7 @@ export class BytecodeCompiler {
38
40
  target: options.target || "vm",
39
41
  debug: options.debug || false,
40
42
  maxSize: options.maxSize || 1048576, // 1MB default
41
- optimizationLevel: options.optimizationLevel || "production", // Default to Production
43
+ optimizationLevel: "production", // Public SDK surface is locked to production
42
44
  sourceFile: sourceFilename,
43
45
  // Pass through metrics options
44
46
  metricsFormat: options.metricsFormat,
@@ -48,7 +50,7 @@ export class BytecodeCompiler {
48
50
  comprehensiveMetrics: options.comprehensiveMetrics,
49
51
  };
50
52
  // Perform compilation
51
- const result = await this.wasmCompiler.compile(sourceContent, compilerOptions);
53
+ const result = await this.wasmCompiler.compile(normalizedSourceContent, compilerOptions);
52
54
  const compilationTime = Date.now() - startTime;
53
55
  if (result.success && result.bytecode) {
54
56
  let abiData = result.abi;
@@ -114,7 +116,7 @@ export class BytecodeCompiler {
114
116
  : undefined;
115
117
  throw new CompilationSDKError(`Compilation error: ${error instanceof Error ? error.message : "Unknown error"}`, {
116
118
  ...(inheritedDetails || {}),
117
- source: sourceContent.substring(0, 200),
119
+ source: normalizedSourceContent.substring(0, 200),
118
120
  options,
119
121
  });
120
122
  }
@@ -216,6 +218,7 @@ export class BytecodeCompiler {
216
218
  */
217
219
  async validateSource(source) {
218
220
  const code = typeof source === 'string' ? source : source.content;
221
+ const normalizedCode = normalizeWasmCompilerSource(code);
219
222
  if (this.debug) {
220
223
  console.log(`[BytecodeCompiler] Validating source (${code.length} chars)...`);
221
224
  }
@@ -223,7 +226,7 @@ export class BytecodeCompiler {
223
226
  if (!this.wasmCompiler) {
224
227
  await this.loadWasmCompiler();
225
228
  }
226
- const result = await this.wasmCompiler.validateSource(code);
229
+ const result = await this.wasmCompiler.validateSource(normalizedCode);
227
230
  return {
228
231
  valid: result.valid,
229
232
  errors: result.errors ? this.transformErrors(result.errors) : undefined,
@@ -372,6 +375,7 @@ export class BytecodeCompiler {
372
375
  */
373
376
  async generateABI(source) {
374
377
  const code = typeof source === 'string' ? source : source.content;
378
+ const normalizedCode = normalizeWasmCompilerSource(code);
375
379
  if (this.debug) {
376
380
  console.log(`[BytecodeCompiler] Generating ABI for source (${code.length} chars)...`);
377
381
  }
@@ -379,7 +383,7 @@ export class BytecodeCompiler {
379
383
  if (!this.wasmCompiler) {
380
384
  await this.loadWasmCompiler();
381
385
  }
382
- const abi = await this.wasmCompiler.generateABI(code);
386
+ const abi = await this.wasmCompiler.generateABI(normalizedCode);
383
387
  const normalizedFunctions = normalizeAbiFunctions(abi?.functions ?? abi);
384
388
  return { ...abi, functions: normalizedFunctions };
385
389
  }
@@ -387,7 +391,7 @@ export class BytecodeCompiler {
387
391
  if (this.debug) {
388
392
  console.log(`[BytecodeCompiler] ABI generation error: ${error}`);
389
393
  }
390
- throw new CompilationSDKError(`ABI generation failed: ${error instanceof Error ? error.message : "Unknown error"}`, { source: code.substring(0, 100) });
394
+ throw new CompilationSDKError(`ABI generation failed: ${error instanceof Error ? error.message : "Unknown error"}`, { source: normalizedCode.substring(0, 100) });
391
395
  }
392
396
  }
393
397
  /**
@@ -0,0 +1 @@
1
+ export declare function normalizeWasmCompilerSource(source: string): string;
@@ -0,0 +1,67 @@
1
+ const SPL_TOKEN_PROGRAM_ID = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
2
+ function normalizeAccountContextAccess(source) {
3
+ const placeholders = new Map();
4
+ let nextId = 0;
5
+ const protect = (match) => {
6
+ const token = `__FIVE_CTX_${nextId++}__`;
7
+ placeholders.set(token, match);
8
+ return token;
9
+ };
10
+ let normalized = source.replace(/(\b[A-Za-z_][A-Za-z0-9_]*)\.ctx\.(key|lamports|owner|data|bump)\b/g, protect);
11
+ normalized = normalized.replace(/(\b[A-Za-z_][A-Za-z0-9_]*)\.(key|lamports|owner|data|bump)\b/g, '$1.ctx.$2');
12
+ for (const [token, original] of placeholders.entries()) {
13
+ normalized = normalized.split(token).join(original);
14
+ }
15
+ return normalized;
16
+ }
17
+ function normalizeSplTokenModule(source) {
18
+ const importPattern = /^\s*use\s+std::interfaces::spl_token;\s*$/m;
19
+ if (!importPattern.test(source) && !/\bspl_token::[A-Za-z_][A-Za-z0-9_]*\s*\(/.test(source)) {
20
+ return source;
21
+ }
22
+ let normalized = source.replace(importPattern, '');
23
+ const methods = new Set();
24
+ for (const match of normalized.matchAll(/\bspl_token::([A-Za-z_][A-Za-z0-9_]*)\s*\(/g)) {
25
+ methods.add(match[1]);
26
+ }
27
+ if (methods.size === 0) {
28
+ return normalized;
29
+ }
30
+ const signatures = Array.from(methods)
31
+ .sort()
32
+ .map((method) => {
33
+ switch (method) {
34
+ case 'transfer':
35
+ return ' transfer(source: account @mut, destination: account @mut, authority: account @signer, amount: u64);';
36
+ case 'mint_to':
37
+ return ' mint_to(mint: account @mut, destination: account @mut, authority: account @signer, amount: u64);';
38
+ case 'burn':
39
+ return ' burn(source: account @mut, mint: account @mut, authority: account @signer, amount: u64);';
40
+ case 'approve':
41
+ return ' approve(source: account @mut, delegate: account, authority: account @signer, amount: u64);';
42
+ case 'revoke':
43
+ return ' revoke(source: account @mut, authority: account @signer);';
44
+ case 'freeze_account':
45
+ return ' freeze_account(account_to_freeze: account @mut, mint: account @mut, freeze_authority: account @signer);';
46
+ case 'thaw_account':
47
+ return ' thaw_account(account_to_thaw: account @mut, mint: account @mut, freeze_authority: account @signer);';
48
+ case 'transfer_checked':
49
+ return ' transfer_checked(source: account @mut, mint: account @mut, destination: account @mut, authority: account @signer, amount: u64, decimals: u8);';
50
+ default:
51
+ return ` ${method}(source: account @mut, destination: account @mut, authority: account @signer, amount: u64);`;
52
+ }
53
+ })
54
+ .join('\n');
55
+ normalized = normalized.replace(/\bspl_token::([A-Za-z_][A-Za-z0-9_]*)\s*\(/g, 'SPLToken.$1(');
56
+ if (/^\s*interface\s+SPLToken\b/m.test(normalized)) {
57
+ return normalized;
58
+ }
59
+ const interfaceDecl = `interface SPLToken @program("${SPL_TOKEN_PROGRAM_ID}") {\n${signatures}\n}\n\n`;
60
+ return `${interfaceDecl}${normalized.trimStart()}`;
61
+ }
62
+ export function normalizeWasmCompilerSource(source) {
63
+ let normalized = source;
64
+ normalized = normalizeAccountContextAccess(normalized);
65
+ normalized = normalizeSplTokenModule(normalized);
66
+ return normalized;
67
+ }
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { validator } from '../validation/index.js';
6
6
  import { VmClusterConfigResolver } from './VmClusterConfigResolver.js';
7
+ import { FIVE_VM_PROGRAM_ID } from '../types.js';
7
8
  /**
8
9
  * Centralized resolver for program IDs across all SDK operations.
9
10
  * Ensures consistent validation and error messaging.
@@ -45,7 +46,7 @@ export class ProgramIdResolver {
45
46
  * ```
46
47
  */
47
48
  static resolve(explicit, options) {
48
- // Precedence: explicit → default → cluster-config
49
+ // Precedence: explicit → default → env → cluster-config → baked
49
50
  let resolved;
50
51
  if (explicit) {
51
52
  resolved = explicit;
@@ -53,12 +54,15 @@ export class ProgramIdResolver {
53
54
  else if (this.defaultProgramId) {
54
55
  resolved = this.defaultProgramId;
55
56
  }
57
+ else if (process.env.FIVE_PROGRAM_ID) {
58
+ resolved = process.env.FIVE_PROGRAM_ID;
59
+ }
56
60
  else {
57
61
  try {
58
62
  resolved = VmClusterConfigResolver.loadClusterConfig().programId;
59
63
  }
60
64
  catch {
61
- resolved = undefined;
65
+ resolved = FIVE_VM_PROGRAM_ID;
62
66
  }
63
67
  }
64
68
  if (!resolved && !options?.allowUndefined) {
@@ -0,0 +1,2 @@
1
+ export declare const SCRIPT_BYTECODE_HEADER_V1_LEN = 10;
2
+ export declare const SCRIPT_ACCOUNT_HEADER_LEN = 64;
@@ -0,0 +1,2 @@
1
+ export const SCRIPT_BYTECODE_HEADER_V1_LEN = 10;
2
+ export const SCRIPT_ACCOUNT_HEADER_LEN = 64;
@@ -9,9 +9,10 @@ export declare class PDAUtils {
9
9
  /**
10
10
  * Derive script account using seed-based derivation compatible with SystemProgram.createAccountWithSeed
11
11
  * @param bytecode - The bytecode to derive address for
12
+ * @param basePublicKey - The deployer/base public key used for createWithSeed
12
13
  * @param programId - The Five VM program ID (required - no default to enforce explicit configuration)
13
14
  */
14
- static deriveScriptAccount(bytecode: Uint8Array, programId: string): Promise<{
15
+ static deriveScriptAccount(bytecode: Uint8Array, basePublicKey: string, programId: string): Promise<{
15
16
  address: string;
16
17
  bump: number;
17
18
  seed: string;
@@ -127,6 +128,12 @@ export declare class RentCalculator {
127
128
  * Calculate minimum rent-exempt balance for account size (legacy method)
128
129
  */
129
130
  static calculateRentExemption(accountSize: number): number;
131
+ /**
132
+ * Query rent from RPC when possible and fall back to local estimation otherwise.
133
+ */
134
+ static calculateRentExemptionWithConnection(accountSize: number, connection?: {
135
+ getMinimumBalanceForRentExemption?: (size: number) => Promise<number>;
136
+ }): Promise<number>;
130
137
  /**
131
138
  * Get estimated rent for script account based on bytecode size
132
139
  */