@5ive-tech/sdk 1.1.12 → 1.1.14

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 (45) hide show
  1. package/README.md +16 -0
  2. package/dist/FiveSDK.d.ts +45 -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/compiler/BytecodeCompiler.js +10 -6
  11. package/dist/compiler/source-normalization.d.ts +1 -0
  12. package/dist/compiler/source-normalization.js +67 -0
  13. package/dist/constants/headers.d.ts +2 -0
  14. package/dist/constants/headers.js +2 -0
  15. package/dist/crypto/index.d.ts +8 -1
  16. package/dist/crypto/index.js +27 -14
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.js +1 -0
  19. package/dist/modules/accounts.js +1 -1
  20. package/dist/modules/deploy.js +172 -99
  21. package/dist/modules/execute.d.ts +5 -0
  22. package/dist/modules/execute.js +115 -49
  23. package/dist/modules/fees.js +2 -2
  24. package/dist/modules/namespaces.d.ts +11 -0
  25. package/dist/modules/namespaces.js +64 -0
  26. package/dist/program/FiveProgram.js +4 -3
  27. package/dist/program/FunctionBuilder.d.ts +8 -0
  28. package/dist/program/FunctionBuilder.js +18 -5
  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/TestDiscovery.d.ts +1 -0
  33. package/dist/testing/TestDiscovery.js +18 -2
  34. package/dist/testing/TestRunner.js +4 -1
  35. package/dist/types.d.ts +16 -5
  36. package/dist/types.js +1 -0
  37. package/dist/utils/abi.js +33 -10
  38. package/dist/utils/transaction.d.ts +16 -0
  39. package/dist/utils/transaction.js +81 -5
  40. package/dist/wasm/compiler/CompilationLogic.js +3 -3
  41. package/dist/wasm/vm.d.ts +2 -2
  42. package/dist/wasm/vm.js +10 -11
  43. package/package.json +1 -1
  44. package/dist/assets/vm/dummy.file +0 -0
  45. package/dist/assets/vm/five_vm_wasm_bg.js +0 -3307
package/dist/index.d.ts CHANGED
@@ -15,6 +15,7 @@ export * from './wasm/vm.js';
15
15
  export * from './wasm/compiler/index.js';
16
16
  export * from './wasm/loader.js';
17
17
  export * from './testing/index.js';
18
+ export * from './utils/abi.js';
18
19
  export * from './program/index.js';
19
20
  export * from './modules/namespaces.js';
20
21
  export { ProgramIdResolver } from './config/ProgramIdResolver.js';
package/dist/index.js CHANGED
@@ -17,6 +17,7 @@ export * from './wasm/vm.js';
17
17
  export * from './wasm/compiler/index.js';
18
18
  export * from './wasm/loader.js';
19
19
  export * from './testing/index.js';
20
+ export * from './utils/abi.js';
20
21
  // ==================== FiveProgram High-Level API ====================
21
22
  export * from './program/index.js';
22
23
  export * from './modules/namespaces.js';
@@ -255,7 +255,7 @@ export async function validateBytecodeEncoding(bytecode, debug = false) {
255
255
  error: 'Invalid Five VM magic bytes (expected "5IVE")',
256
256
  };
257
257
  }
258
- // Optimized Header V3:
258
+ // ScriptBytecodeHeaderV1:
259
259
  // 0-3: Magic
260
260
  // 4-7: Features (u32 LE)
261
261
  // 8: Public Function Count (u8)
@@ -1,9 +1,10 @@
1
1
  import { PDAUtils, RentCalculator } from "../crypto/index.js";
2
2
  import { validator, Validators } from "../validation/index.js";
3
3
  import { calculateDeployFee } from "./fees.js";
4
- import { confirmTransactionRobust, getAccountInfoWithRetry, pollForConfirmation, SDK_COMMITMENTS, } from "../utils/transaction.js";
4
+ import { getAccountInfoWithRetry, sendAndConfirmRawTransactionRobust, SDK_COMMITMENTS, } from "../utils/transaction.js";
5
5
  import { ProgramIdResolver } from "../config/ProgramIdResolver.js";
6
6
  import { VmClusterConfigResolver } from "../config/VmClusterConfigResolver.js";
7
+ import { SCRIPT_ACCOUNT_HEADER_LEN } from "../constants/headers.js";
7
8
  const DEFAULT_FEE_VAULT_SHARD_COUNT = (() => {
8
9
  try {
9
10
  return VmClusterConfigResolver.loadClusterConfig().feeVaultShardCount;
@@ -16,6 +17,24 @@ const FEE_VAULT_NAMESPACE_SEED = Buffer.from([
16
17
  0xff, 0x66, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x6d, 0x5f, 0x66, 0x65, 0x65,
17
18
  0x5f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x31,
18
19
  ]);
20
+ function clampShardCount(rawCount) {
21
+ const normalized = rawCount > 0 ? rawCount : DEFAULT_FEE_VAULT_SHARD_COUNT;
22
+ return Math.max(1, Math.min(DEFAULT_FEE_VAULT_SHARD_COUNT, normalized));
23
+ }
24
+ function normalizeRpcEndpoint(connection) {
25
+ return String(connection?.rpcEndpoint || connection?._rpcEndpoint || "").toLowerCase();
26
+ }
27
+ function isLocalnetBootstrapConnection(connection, network) {
28
+ const normalizedNetwork = String(network || "").toLowerCase();
29
+ if (normalizedNetwork === "localnet") {
30
+ return true;
31
+ }
32
+ const endpoint = normalizeRpcEndpoint(connection);
33
+ return endpoint.includes("127.0.0.1") || endpoint.includes("localhost");
34
+ }
35
+ function selectBootstrapCommitment(connection, network) {
36
+ return isLocalnetBootstrapConnection(connection, network) ? "confirmed" : "finalized";
37
+ }
19
38
  async function readVMStateFeeConfig(connection, vmStateAddress) {
20
39
  if (!connection) {
21
40
  return { shardCount: DEFAULT_FEE_VAULT_SHARD_COUNT };
@@ -37,7 +56,7 @@ async function readVMStateFeeConfig(connection, vmStateAddress) {
37
56
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
38
57
  const deployFeeLamports = view.getUint32(40, true);
39
58
  const shardCountRaw = data.length > 50 ? data[50] : 0;
40
- const shardCount = shardCountRaw > 0 ? shardCountRaw : DEFAULT_FEE_VAULT_SHARD_COUNT;
59
+ const shardCount = clampShardCount(shardCountRaw);
41
60
  return { deployFeeLamports, shardCount };
42
61
  }
43
62
  catch {
@@ -49,16 +68,50 @@ async function deriveProgramFeeVault(programId, shardIndex) {
49
68
  const [pda, bump] = PublicKey.findProgramAddressSync([FEE_VAULT_NAMESPACE_SEED, Buffer.from([shardIndex])], new PublicKey(programId));
50
69
  return { address: pda.toBase58(), bump };
51
70
  }
71
+ async function resolveScriptAccountDerivation(bytecode, deployer, programId, options) {
72
+ const { PublicKey } = await import("@solana/web3.js");
73
+ if (options.scriptAccount) {
74
+ validator.validateBase58Address(options.scriptAccount, "options.scriptAccount");
75
+ if (!options.scriptSeed) {
76
+ throw new Error("options.scriptSeed is required when options.scriptAccount is provided");
77
+ }
78
+ const expectedAccount = await PublicKey.createWithSeed(new PublicKey(deployer), options.scriptSeed, new PublicKey(programId));
79
+ if (expectedAccount.toBase58() !== options.scriptAccount) {
80
+ throw new Error("options.scriptAccount does not match the derived address for the provided deployer, scriptSeed, and programId");
81
+ }
82
+ return {
83
+ address: options.scriptAccount,
84
+ bump: 0,
85
+ seed: options.scriptSeed,
86
+ };
87
+ }
88
+ return PDAUtils.deriveScriptAccount(bytecode, deployer, programId);
89
+ }
52
90
  function createInitFeeVaultInstructionData(shardIndex, bump) {
53
91
  return Uint8Array.from([11, shardIndex & 0xff, bump & 0xff]);
54
92
  }
55
93
  async function initProgramFeeVaultShards(connection, programId, vmStateAccount, shardCount, payer, options = {}) {
56
94
  const { PublicKey, Transaction, TransactionInstruction, SystemProgram } = await import("@solana/web3.js");
57
95
  const signatures = [];
58
- for (let shardIndex = 0; shardIndex < shardCount; shardIndex++) {
96
+ const effectiveShardCount = clampShardCount(shardCount);
97
+ const programPubkey = new PublicKey(programId);
98
+ const bootstrapCommitment = selectBootstrapCommitment(connection);
99
+ for (let shardIndex = 0; shardIndex < effectiveShardCount; shardIndex++) {
59
100
  const vault = await deriveProgramFeeVault(programId, shardIndex);
101
+ const existingVault = await getAccountInfoWithRetry(connection, new PublicKey(vault.address), {
102
+ commitment: bootstrapCommitment,
103
+ retries: 1,
104
+ delayMs: 500,
105
+ debug: options.debug,
106
+ });
107
+ if (existingVault?.owner && new PublicKey(existingVault.owner).equals(programPubkey)) {
108
+ if (options.debug) {
109
+ console.log(`[FiveSDK] Fee vault shard ${shardIndex} already initialized: ${vault.address}`);
110
+ }
111
+ continue;
112
+ }
60
113
  const tx = new Transaction().add(new TransactionInstruction({
61
- programId: new PublicKey(programId),
114
+ programId: programPubkey,
62
115
  keys: [
63
116
  { pubkey: new PublicKey(vmStateAccount), isSigner: false, isWritable: false },
64
117
  { pubkey: payer.publicKey, isSigner: true, isWritable: true },
@@ -67,24 +120,24 @@ async function initProgramFeeVaultShards(connection, programId, vmStateAccount,
67
120
  ],
68
121
  data: Buffer.from(createInitFeeVaultInstructionData(shardIndex, vault.bump)),
69
122
  }));
70
- const { blockhash } = await connection.getLatestBlockhash("confirmed");
71
- tx.recentBlockhash = blockhash;
123
+ const latestBlockhash = await connection.getLatestBlockhash("confirmed");
124
+ tx.recentBlockhash = latestBlockhash.blockhash;
72
125
  tx.feePayer = payer.publicKey;
73
126
  tx.partialSign(payer);
74
- const sig = await connection.sendRawTransaction(tx.serialize(), {
75
- skipPreflight: true,
76
- preflightCommitment: "confirmed",
77
- maxRetries: options.maxRetries || 3,
78
- });
79
- const shardConfirm = await confirmTransactionRobust(connection, sig, {
80
- commitment: "finalized",
127
+ const shardSend = await sendAndConfirmRawTransactionRobust(connection, tx.serialize(), {
128
+ commitment: bootstrapCommitment,
81
129
  timeoutMs: 120000,
82
130
  debug: options.debug,
131
+ maxRetries: options.maxRetries || 3,
132
+ skipPreflight: false,
133
+ preflightCommitment: "confirmed",
134
+ blockhash: latestBlockhash.blockhash,
135
+ lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
83
136
  });
84
- if (!shardConfirm.success) {
85
- throw new Error(`Fee vault shard init failed: ${shardConfirm.error || "unconfirmed"}`);
137
+ if (!shardSend.success || !shardSend.signature) {
138
+ throw new Error(`Fee vault shard init failed: ${shardSend.error || "unconfirmed"}`);
86
139
  }
87
- signatures.push(sig);
140
+ signatures.push(shardSend.signature);
88
141
  if (options.debug) {
89
142
  console.log(`[FiveSDK] Initialized fee vault shard ${shardIndex}: ${vault.address}`);
90
143
  }
@@ -95,9 +148,6 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
95
148
  Validators.bytecode(bytecode);
96
149
  validator.validateBase58Address(deployer, "deployer");
97
150
  Validators.options(options);
98
- if (options.scriptAccount) {
99
- validator.validateBase58Address(options.scriptAccount, "options.scriptAccount");
100
- }
101
151
  // Resolve program ID with consistent precedence
102
152
  const programId = ProgramIdResolver.resolve(fiveVMProgramId || options.fiveVMProgramId);
103
153
  const exportMetadata = encodeExportMetadata(options.exportMetadata);
@@ -105,7 +155,7 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
105
155
  console.log(`[FiveSDK] Generating deployment transaction (${bytecode.length} bytes)...`);
106
156
  console.log(`[FiveSDK] Using program ID: ${programId}`);
107
157
  }
108
- const scriptResult = await PDAUtils.deriveScriptAccount(bytecode, programId);
158
+ const scriptResult = await resolveScriptAccountDerivation(bytecode, deployer, programId, options);
109
159
  const scriptAccount = scriptResult.address;
110
160
  const scriptSeed = scriptResult.seed;
111
161
  const vmStatePDAResult = await PDAUtils.deriveVMStatePDA(programId);
@@ -114,9 +164,8 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
114
164
  console.log(`[FiveSDK] Script Account: ${scriptAccount} (seed: ${scriptSeed})`);
115
165
  console.log(`[FiveSDK] VM State PDA: ${vmStatePDA}`);
116
166
  }
117
- const SCRIPT_HEADER_SIZE = 64; // ScriptAccountHeader size from Rust program
118
- const totalAccountSize = SCRIPT_HEADER_SIZE + exportMetadata.length + bytecode.length;
119
- const rentLamports = await RentCalculator.calculateRentExemption(totalAccountSize);
167
+ const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
168
+ const rentLamports = await RentCalculator.calculateRentExemptionWithConnection(totalAccountSize, connection);
120
169
  const { deployFeeLamports } = await readVMStateFeeConfig(connection, vmStatePDA);
121
170
  const deployShardIndex = 0;
122
171
  const deployVault = await deriveProgramFeeVault(programId, deployShardIndex);
@@ -191,9 +240,8 @@ options = {}) {
191
240
  const scriptKeypair = Keypair.generate();
192
241
  const scriptAccount = scriptKeypair.publicKey.toString();
193
242
  // Calculate account size and rent
194
- const SCRIPT_HEADER_SIZE = 64; // ScriptHeader::LEN
195
243
  const exportMetadata = encodeExportMetadata(options.exportMetadata);
196
- const totalAccountSize = SCRIPT_HEADER_SIZE + exportMetadata.length + bytecode.length;
244
+ const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
197
245
  const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
198
246
  const vmStatePDA = await PDAUtils.deriveVMStatePDA(programIdStr);
199
247
  const vmStatePubkey = new PublicKey(vmStatePDA.address);
@@ -211,7 +259,8 @@ options = {}) {
211
259
  }));
212
260
  }
213
261
  // 1. Initialize canonical VM State if missing
214
- const vmStateInfo = await connection.getAccountInfo(vmStatePubkey, "finalized");
262
+ const bootstrapCommitment = selectBootstrapCommitment(connection);
263
+ const vmStateInfo = await connection.getAccountInfo(vmStatePubkey, bootstrapCommitment);
215
264
  if (!vmStateInfo) {
216
265
  tx.add(new TransactionInstruction({
217
266
  keys: [
@@ -275,17 +324,18 @@ options = {}) {
275
324
  console.log(`[FiveSDK] Generated script keypair: ${scriptAccount}`);
276
325
  }
277
326
  // Calculate account size and rent
278
- const SCRIPT_HEADER_SIZE = 64; // ScriptHeader::LEN (five-protocol)
279
327
  const exportMetadata = encodeExportMetadata(options.exportMetadata);
280
- const totalAccountSize = SCRIPT_HEADER_SIZE + exportMetadata.length + bytecode.length;
328
+ const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
281
329
  const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
282
330
  const vmStateResolution = await ensureCanonicalVmStateAccount(connection, deployerKeypair, new PublicKey(programId), {
283
331
  vmStateAccount: options.vmStateAccount,
284
332
  maxRetries: options.maxRetries,
285
333
  debug: options.debug,
334
+ network: options.network,
286
335
  });
287
336
  const vmStatePubkey = vmStateResolution.vmStatePubkey;
288
337
  const vmStateRent = vmStateResolution.vmStateRent;
338
+ const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
289
339
  const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
290
340
  const deployShardIndex = 0;
291
341
  const deployVault = await deriveProgramFeeVault(programId, deployShardIndex);
@@ -308,7 +358,7 @@ options = {}) {
308
358
  console.log(`[FiveSDK] Export metadata size: ${exportMetadata.length} bytes`);
309
359
  console.log(`[FiveSDK] Rent cost: ${((rentLamports + vmStateRent) / 1e9)} SOL`);
310
360
  }
311
- const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programId, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries });
361
+ const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programId, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries, network: options.network });
312
362
  // SINGLE TRANSACTION: create script account + deploy bytecode
313
363
  const tx = new Transaction();
314
364
  // Optional compute budget
@@ -373,19 +423,20 @@ options = {}) {
373
423
  if (options.debug) {
374
424
  console.log(`[FiveSDK] Transaction serialized: ${txSerialized.length} bytes`);
375
425
  }
376
- const signature = await connection.sendRawTransaction(txSerialized, {
377
- skipPreflight: true,
378
- preflightCommitment: "confirmed",
426
+ const sendResult = await sendAndConfirmRawTransactionRobust(connection, txSerialized, {
427
+ commitment: "confirmed",
428
+ timeoutMs: 120000,
429
+ debug: options.debug,
379
430
  maxRetries: options.maxRetries || 3,
431
+ skipPreflight: false,
432
+ preflightCommitment: "confirmed",
380
433
  });
434
+ const signature = sendResult.signature;
381
435
  if (options.debug) {
382
436
  console.log(`[FiveSDK] sendRawTransaction completed, returned signature: ${signature}`);
383
437
  }
384
- // Custom confirmation polling with extended timeout (120 seconds)
385
- const confirmationResult = await pollForConfirmation(connection, signature, "confirmed", 120000, // 120 second timeout
386
- options.debug);
387
- if (!confirmationResult.success) {
388
- const errorMessage = `Deployment confirmation failed: ${confirmationResult.error || "Unknown error"}`;
438
+ if (!sendResult.success || !signature) {
439
+ const errorMessage = `Deployment confirmation failed: ${sendResult.error || "Unknown error"}`;
389
440
  if (options.debug)
390
441
  console.log(`[FiveSDK] ${errorMessage}`);
391
442
  return {
@@ -394,8 +445,8 @@ options = {}) {
394
445
  transactionId: signature,
395
446
  };
396
447
  }
397
- if (confirmationResult.err) {
398
- const errorMessage = `Combined deployment failed: ${JSON.stringify(confirmationResult.err)}`;
448
+ if (sendResult.err) {
449
+ const errorMessage = `Combined deployment failed: ${JSON.stringify(sendResult.err)}`;
399
450
  if (options.debug)
400
451
  console.log(`[FiveSDK] ${errorMessage}`);
401
452
  return {
@@ -463,8 +514,7 @@ options = {}) {
463
514
  const scriptKeypair = Keypair.generate();
464
515
  const scriptAccount = scriptKeypair.publicKey.toString();
465
516
  // Calculate account size and rent
466
- const SCRIPT_HEADER_SIZE = 64; // ScriptHeader::LEN (five-protocol)
467
- const totalAccountSize = SCRIPT_HEADER_SIZE + bytecode.length;
517
+ const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
468
518
  const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
469
519
  const programIdStr = ProgramIdResolver.resolve(options.fiveVMProgramId);
470
520
  const programId = new PublicKey(programIdStr);
@@ -472,9 +522,11 @@ options = {}) {
472
522
  vmStateAccount: options.vmStateAccount,
473
523
  maxRetries: options.maxRetries,
474
524
  debug: options.debug,
525
+ network: options.network,
475
526
  });
476
527
  const vmStatePubkey = vmStateResolution.vmStatePubkey;
477
528
  const vmStateRent = vmStateResolution.vmStateRent;
529
+ const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
478
530
  const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
479
531
  const deployShardIndex = 0;
480
532
  const deployVault = await deriveProgramFeeVault(programIdStr, deployShardIndex);
@@ -496,7 +548,7 @@ options = {}) {
496
548
  console.log(`[FiveSDK] Total account size: ${totalAccountSize} bytes`);
497
549
  console.log(`[FiveSDK] Initial rent cost: ${(rentLamports + vmStateRent) / 1e9} SOL`);
498
550
  }
499
- const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries });
551
+ const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries, network: options.network });
500
552
  const transactionIds = [];
501
553
  let totalCost = rentLamports + vmStateRent;
502
554
  // TRANSACTION 1: Create Account + InitLargeProgram
@@ -509,7 +561,7 @@ options = {}) {
509
561
  fromPubkey: deployerKeypair.publicKey,
510
562
  newAccountPubkey: scriptKeypair.publicKey,
511
563
  lamports: rentLamports,
512
- space: SCRIPT_HEADER_SIZE, // Start with just header space
564
+ space: SCRIPT_ACCOUNT_HEADER_LEN, // Start with just the ScriptAccountHeader
513
565
  programId: programId,
514
566
  });
515
567
  initTransaction.add(createAccountInstruction);
@@ -530,7 +582,7 @@ options = {}) {
530
582
  {
531
583
  pubkey: vmStatePubkey,
532
584
  isSigner: false,
533
- isWritable: false,
585
+ isWritable: true,
534
586
  },
535
587
  ...feeVaultKeys,
536
588
  ],
@@ -540,23 +592,24 @@ options = {}) {
540
592
  initTransaction.add(initLargeProgramInstruction);
541
593
  // Sign and send initialization transaction
542
594
  initTransaction.feePayer = deployerKeypair.publicKey;
543
- const { blockhash } = await connection.getLatestBlockhash("confirmed");
544
- initTransaction.recentBlockhash = blockhash;
595
+ const initBlockhash = await connection.getLatestBlockhash("confirmed");
596
+ initTransaction.recentBlockhash = initBlockhash.blockhash;
545
597
  initTransaction.partialSign(deployerKeypair);
546
598
  initTransaction.partialSign(scriptKeypair);
547
- const initSignature = await connection.sendRawTransaction(initTransaction.serialize(), {
548
- skipPreflight: true,
549
- preflightCommitment: "confirmed",
550
- maxRetries: options.maxRetries || 3,
551
- });
552
- const initConfirm = await confirmTransactionRobust(connection, initSignature, {
553
- commitment: "finalized",
599
+ const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
600
+ commitment: bootstrapCommitment,
554
601
  timeoutMs: 120000,
555
602
  debug: options.debug,
603
+ maxRetries: options.maxRetries || 3,
604
+ skipPreflight: false,
605
+ preflightCommitment: "confirmed",
606
+ blockhash: initBlockhash.blockhash,
607
+ lastValidBlockHeight: initBlockhash.lastValidBlockHeight,
556
608
  });
557
- if (!initConfirm.success) {
558
- throw new Error(`Initialization confirmation failed: ${initConfirm.error || "unconfirmed"}`);
609
+ if (!initSend.success || !initSend.signature) {
610
+ throw new Error(`Initialization confirmation failed: ${initSend.error || "unconfirmed"}`);
559
611
  }
612
+ const initSignature = initSend.signature;
560
613
  transactionIds.push(initSignature);
561
614
  if (options.debug) {
562
615
  console.log(`[FiveSDK] ✅ Initialization completed: ${initSignature}`);
@@ -575,7 +628,7 @@ options = {}) {
575
628
  console.log(`[FiveSDK] Step ${i + 2}: Appending chunk ${i + 1}/${chunks.length} (${chunk.length} bytes)`);
576
629
  }
577
630
  // Calculate additional rent needed for this chunk
578
- const currentInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, { commitment: "finalized", retries: 2, delayMs: 1000, debug: options.debug });
631
+ const currentInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, { commitment: bootstrapCommitment, retries: 2, delayMs: 1000, debug: options.debug });
579
632
  if (!currentInfo)
580
633
  throw new Error("Script account not found after initialization");
581
634
  const newSize = currentInfo.data.length + chunk.length;
@@ -628,7 +681,7 @@ options = {}) {
628
681
  {
629
682
  pubkey: vmStatePubkey,
630
683
  isSigner: false,
631
- isWritable: false,
684
+ isWritable: true,
632
685
  },
633
686
  ...feeVaultKeys,
634
687
  ],
@@ -641,19 +694,20 @@ options = {}) {
641
694
  appendTransaction.feePayer = deployerKeypair.publicKey;
642
695
  appendTransaction.recentBlockhash = appendBlockhash.blockhash;
643
696
  appendTransaction.partialSign(deployerKeypair);
644
- const appendSignature = await connection.sendRawTransaction(appendTransaction.serialize(), {
645
- skipPreflight: true,
646
- preflightCommitment: "confirmed",
647
- maxRetries: options.maxRetries || 3,
648
- });
649
- const appendConfirm = await confirmTransactionRobust(connection, appendSignature, {
650
- commitment: "finalized",
697
+ const appendSend = await sendAndConfirmRawTransactionRobust(connection, appendTransaction.serialize(), {
698
+ commitment: bootstrapCommitment,
651
699
  timeoutMs: 120000,
652
700
  debug: options.debug,
701
+ maxRetries: options.maxRetries || 3,
702
+ skipPreflight: false,
703
+ preflightCommitment: "confirmed",
704
+ blockhash: appendBlockhash.blockhash,
705
+ lastValidBlockHeight: appendBlockhash.lastValidBlockHeight,
653
706
  });
654
- if (!appendConfirm.success) {
655
- throw new Error(`Append confirmation failed: ${appendConfirm.error || "unconfirmed"}`);
707
+ if (!appendSend.success || !appendSend.signature) {
708
+ throw new Error(`Append confirmation failed: ${appendSend.error || "unconfirmed"}`);
656
709
  }
710
+ const appendSignature = appendSend.signature;
657
711
  transactionIds.push(appendSignature);
658
712
  if (options.debug) {
659
713
  console.log(`[FiveSDK] ✅ Chunk ${i + 1} appended: ${appendSignature}`);
@@ -661,7 +715,7 @@ options = {}) {
661
715
  }
662
716
  // Final verification
663
717
  let finalInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, {
664
- commitment: "finalized",
718
+ commitment: bootstrapCommitment,
665
719
  retries: 2,
666
720
  delayMs: 1000,
667
721
  debug: options.debug,
@@ -669,7 +723,7 @@ options = {}) {
669
723
  if (!finalInfo) {
670
724
  throw new Error("Script account not found during final verification");
671
725
  }
672
- const expectedSize = SCRIPT_HEADER_SIZE + bytecode.length;
726
+ const expectedSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
673
727
  if (options.debug) {
674
728
  console.log(`[FiveSDK] 🔍 Final verification:`);
675
729
  console.log(`[FiveSDK] Expected size: ${expectedSize} bytes`);
@@ -733,8 +787,7 @@ options = {}) {
733
787
  const scriptKeypair = Keypair.generate();
734
788
  const scriptAccount = scriptKeypair.publicKey.toString();
735
789
  // Calculate full account size upfront
736
- const SCRIPT_HEADER_SIZE = 64; // ScriptAccountHeader::LEN
737
- const totalAccountSize = SCRIPT_HEADER_SIZE + bytecode.length;
790
+ const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
738
791
  const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
739
792
  const programIdStr = ProgramIdResolver.resolve(options.fiveVMProgramId);
740
793
  const programId = new PublicKey(programIdStr);
@@ -742,9 +795,11 @@ options = {}) {
742
795
  vmStateAccount: options.vmStateAccount,
743
796
  maxRetries: options.maxRetries,
744
797
  debug: options.debug,
798
+ network: options.network,
745
799
  });
746
800
  const vmStatePubkey = vmStateResolution.vmStatePubkey;
747
801
  const vmStateRent = vmStateResolution.vmStateRent;
802
+ const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
748
803
  const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
749
804
  const deployShardIndex = 0;
750
805
  const deployVault = await deriveProgramFeeVault(programIdStr, deployShardIndex);
@@ -766,7 +821,7 @@ options = {}) {
766
821
  console.log(`[FiveSDK] PRE-ALLOCATED full account size: ${totalAccountSize} bytes`);
767
822
  console.log(`[FiveSDK] Full rent cost paid upfront: ${(rentLamports + vmStateRent) / 1e9} SOL`);
768
823
  }
769
- const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries });
824
+ const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries, network: options.network });
770
825
  const transactionIds = [];
771
826
  let totalCost = rentLamports + vmStateRent;
772
827
  const chunks = chunkBytecode(bytecode, chunkSize);
@@ -803,7 +858,7 @@ options = {}) {
803
858
  {
804
859
  pubkey: vmStatePubkey,
805
860
  isSigner: false,
806
- isWritable: false,
861
+ isWritable: true,
807
862
  },
808
863
  ...feeVaultKeys,
809
864
  ],
@@ -816,19 +871,24 @@ options = {}) {
816
871
  initTransaction.recentBlockhash = blockhash;
817
872
  initTransaction.partialSign(deployerKeypair);
818
873
  initTransaction.partialSign(scriptKeypair);
819
- const initSignature = await connection.sendRawTransaction(initTransaction.serialize(), {
820
- skipPreflight: true,
821
- preflightCommitment: "confirmed",
874
+ const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
875
+ commitment: "confirmed",
876
+ timeoutMs: 120000,
877
+ debug: options.debug,
822
878
  maxRetries: options.maxRetries || 3,
879
+ skipPreflight: false,
880
+ preflightCommitment: "confirmed",
881
+ blockhash: blockhash,
882
+ lastValidBlockHeight: undefined,
823
883
  });
824
- const initConfirmation = await pollForConfirmation(connection, initSignature, "confirmed", 120000, options.debug);
825
- if (!initConfirmation.success) {
884
+ if (!initSend.success || !initSend.signature) {
826
885
  return {
827
886
  success: false,
828
- error: `Initialization confirmation failed: ${initConfirmation.error}`,
887
+ error: `Initialization confirmation failed: ${initSend.error}`,
829
888
  transactionIds
830
889
  };
831
890
  }
891
+ const initSignature = initSend.signature;
832
892
  transactionIds.push(initSignature);
833
893
  if (options.debug) {
834
894
  console.log(`[FiveSDK] ✅ Optimized initialization completed: ${initSignature}`);
@@ -911,19 +971,24 @@ options = {}) {
911
971
  appendTransaction.feePayer = deployerKeypair.publicKey;
912
972
  appendTransaction.recentBlockhash = appendBlockhash.blockhash;
913
973
  appendTransaction.partialSign(deployerKeypair);
914
- const appendSignature = await connection.sendRawTransaction(appendTransaction.serialize(), {
915
- skipPreflight: true,
916
- preflightCommitment: "confirmed",
974
+ const appendSend = await sendAndConfirmRawTransactionRobust(connection, appendTransaction.serialize(), {
975
+ commitment: bootstrapCommitment,
976
+ timeoutMs: 120000,
977
+ debug: options.debug,
917
978
  maxRetries: options.maxRetries || 3,
979
+ skipPreflight: false,
980
+ preflightCommitment: "confirmed",
981
+ blockhash: appendBlockhash.blockhash,
982
+ lastValidBlockHeight: appendBlockhash.lastValidBlockHeight,
918
983
  });
919
- const appendConfirmation = await pollForConfirmation(connection, appendSignature, "finalized", 120000, options.debug);
920
- if (!appendConfirmation.success) {
984
+ if (!appendSend.success || !appendSend.signature) {
921
985
  return {
922
986
  success: false,
923
- error: `Append confirmation failed: ${appendConfirmation.error}`,
987
+ error: `Append confirmation failed: ${appendSend.error}`,
924
988
  transactionIds
925
989
  };
926
990
  }
991
+ const appendSignature = appendSend.signature;
927
992
  transactionIds.push(appendSignature);
928
993
  if (options.debug) {
929
994
  console.log(`[FiveSDK] ✅ Multi-chunk append completed: ${appendSignature}`);
@@ -957,17 +1022,20 @@ options = {}) {
957
1022
  const finalizeBlockhash = await connection.getLatestBlockhash("confirmed");
958
1023
  finalizeTransaction.recentBlockhash = finalizeBlockhash.blockhash;
959
1024
  finalizeTransaction.partialSign(deployerKeypair);
960
- const finalizeSignature = await connection.sendRawTransaction(finalizeTransaction.serialize(), {
961
- skipPreflight: true,
962
- preflightCommitment: "confirmed",
1025
+ const finalizeSend = await sendAndConfirmRawTransactionRobust(connection, finalizeTransaction.serialize(), {
1026
+ commitment: bootstrapCommitment,
1027
+ timeoutMs: 120000,
1028
+ debug: options.debug,
963
1029
  maxRetries: options.maxRetries || 3,
1030
+ skipPreflight: false,
1031
+ preflightCommitment: "confirmed",
1032
+ blockhash: finalizeBlockhash.blockhash,
1033
+ lastValidBlockHeight: finalizeBlockhash.lastValidBlockHeight,
964
1034
  });
965
- // Use custom polling for finalize to handle validator latency
966
- const finalizeConfirmation = await pollForConfirmation(connection, finalizeSignature, "finalized", 120000, // 120 second timeout
967
- options.debug);
968
- if (!finalizeConfirmation.success) {
969
- console.error(`[FiveSDK] FinalizeScript confirmation failed: ${finalizeConfirmation.error}`);
1035
+ if (!finalizeSend.success || !finalizeSend.signature) {
1036
+ console.error(`[FiveSDK] FinalizeScript confirmation failed: ${finalizeSend.error}`);
970
1037
  }
1038
+ const finalizeSignature = finalizeSend.signature;
971
1039
  transactionIds.push(finalizeSignature);
972
1040
  if (options.debug) {
973
1041
  console.log(`[FiveSDK] ✅ FinalizeScript completed: ${finalizeSignature}`);
@@ -1090,7 +1158,8 @@ async function ensureCanonicalVmStateAccount(connection, deployerKeypair, progra
1090
1158
  throw new Error(`vmStateAccount must be canonical PDA ${canonical.address}; got ${options.vmStateAccount}`);
1091
1159
  }
1092
1160
  const vmStatePubkey = new PublicKey(canonical.address);
1093
- const existing = await connection.getAccountInfo(vmStatePubkey, "finalized");
1161
+ const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
1162
+ const existing = await connection.getAccountInfo(vmStatePubkey, bootstrapCommitment);
1094
1163
  if (existing) {
1095
1164
  if (existing.owner.toBase58() !== programId.toBase58()) {
1096
1165
  throw new Error(`canonical VM state ${canonical.address} exists but is owned by ${existing.owner.toBase58()}, expected ${programId.toBase58()}`);
@@ -1120,14 +1189,18 @@ async function ensureCanonicalVmStateAccount(connection, deployerKeypair, progra
1120
1189
  const initBlockhash = await connection.getLatestBlockhash("confirmed");
1121
1190
  initTransaction.recentBlockhash = initBlockhash.blockhash;
1122
1191
  initTransaction.partialSign(deployerKeypair);
1123
- const initSignature = await connection.sendRawTransaction(initTransaction.serialize(), {
1124
- skipPreflight: true,
1125
- preflightCommitment: "confirmed",
1192
+ const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
1193
+ commitment: "confirmed",
1194
+ timeoutMs: 120000,
1195
+ debug: options.debug,
1126
1196
  maxRetries: options.maxRetries || 3,
1197
+ skipPreflight: false,
1198
+ preflightCommitment: "confirmed",
1199
+ blockhash: initBlockhash.blockhash,
1200
+ lastValidBlockHeight: initBlockhash.lastValidBlockHeight,
1127
1201
  });
1128
- const initConfirmation = await pollForConfirmation(connection, initSignature, "confirmed", 120000, options.debug);
1129
- if (!initConfirmation.success || initConfirmation.err) {
1130
- throw new Error(`canonical VM state initialization failed: ${initConfirmation.error || JSON.stringify(initConfirmation.err)}`);
1202
+ if (!initSend.success || initSend.err) {
1203
+ throw new Error(`canonical VM state initialization failed: ${initSend.error || JSON.stringify(initSend.err)}`);
1131
1204
  }
1132
1205
  return { vmStatePubkey, vmStateRent, created: true, bump: canonical.bump };
1133
1206
  }
@@ -65,6 +65,11 @@ export declare function executeOnSolana(scriptAccount: string, connection: any,
65
65
  vmStateAccount?: string;
66
66
  fiveVMProgramId?: string;
67
67
  abi?: any;
68
+ accountMetadata?: Map<string, {
69
+ isSigner: boolean;
70
+ isWritable: boolean;
71
+ isSystemAccount?: boolean;
72
+ }>;
68
73
  feeShardIndex?: number;
69
74
  payerAccount?: string;
70
75
  }): Promise<{