@5ive-tech/sdk 1.1.13 → 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 (42) hide show
  1. package/README.md +16 -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/constants/headers.d.ts +2 -0
  15. package/dist/constants/headers.js +2 -0
  16. package/dist/crypto/index.d.ts +8 -1
  17. package/dist/crypto/index.js +27 -14
  18. package/dist/index.d.ts +1 -0
  19. package/dist/index.js +1 -0
  20. package/dist/modules/accounts.js +1 -1
  21. package/dist/modules/deploy.js +165 -97
  22. package/dist/modules/execute.d.ts +5 -0
  23. package/dist/modules/execute.js +107 -49
  24. package/dist/modules/fees.js +2 -2
  25. package/dist/modules/namespaces.d.ts +11 -0
  26. package/dist/modules/namespaces.js +64 -0
  27. package/dist/program/FiveProgram.js +4 -3
  28. package/dist/program/TypeGenerator.js +8 -1
  29. package/dist/project/config.js +113 -1
  30. package/dist/project/workspace.d.ts +5 -0
  31. package/dist/testing/TestDiscovery.d.ts +1 -0
  32. package/dist/testing/TestDiscovery.js +18 -2
  33. package/dist/testing/TestRunner.js +4 -1
  34. package/dist/types.d.ts +16 -5
  35. package/dist/types.js +1 -0
  36. package/dist/utils/abi.js +33 -10
  37. package/dist/utils/transaction.d.ts +16 -0
  38. package/dist/utils/transaction.js +81 -5
  39. package/dist/wasm/compiler/CompilationLogic.js +3 -3
  40. package/dist/wasm/vm.d.ts +2 -2
  41. package/dist/wasm/vm.js +10 -11
  42. package/package.json +1 -1
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;
@@ -20,6 +21,20 @@ function clampShardCount(rawCount) {
20
21
  const normalized = rawCount > 0 ? rawCount : DEFAULT_FEE_VAULT_SHARD_COUNT;
21
22
  return Math.max(1, Math.min(DEFAULT_FEE_VAULT_SHARD_COUNT, normalized));
22
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
+ }
23
38
  async function readVMStateFeeConfig(connection, vmStateAddress) {
24
39
  if (!connection) {
25
40
  return { shardCount: DEFAULT_FEE_VAULT_SHARD_COUNT };
@@ -53,6 +68,25 @@ async function deriveProgramFeeVault(programId, shardIndex) {
53
68
  const [pda, bump] = PublicKey.findProgramAddressSync([FEE_VAULT_NAMESPACE_SEED, Buffer.from([shardIndex])], new PublicKey(programId));
54
69
  return { address: pda.toBase58(), bump };
55
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
+ }
56
90
  function createInitFeeVaultInstructionData(shardIndex, bump) {
57
91
  return Uint8Array.from([11, shardIndex & 0xff, bump & 0xff]);
58
92
  }
@@ -60,10 +94,24 @@ async function initProgramFeeVaultShards(connection, programId, vmStateAccount,
60
94
  const { PublicKey, Transaction, TransactionInstruction, SystemProgram } = await import("@solana/web3.js");
61
95
  const signatures = [];
62
96
  const effectiveShardCount = clampShardCount(shardCount);
97
+ const programPubkey = new PublicKey(programId);
98
+ const bootstrapCommitment = selectBootstrapCommitment(connection);
63
99
  for (let shardIndex = 0; shardIndex < effectiveShardCount; shardIndex++) {
64
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
+ }
65
113
  const tx = new Transaction().add(new TransactionInstruction({
66
- programId: new PublicKey(programId),
114
+ programId: programPubkey,
67
115
  keys: [
68
116
  { pubkey: new PublicKey(vmStateAccount), isSigner: false, isWritable: false },
69
117
  { pubkey: payer.publicKey, isSigner: true, isWritable: true },
@@ -72,24 +120,24 @@ async function initProgramFeeVaultShards(connection, programId, vmStateAccount,
72
120
  ],
73
121
  data: Buffer.from(createInitFeeVaultInstructionData(shardIndex, vault.bump)),
74
122
  }));
75
- const { blockhash } = await connection.getLatestBlockhash("confirmed");
76
- tx.recentBlockhash = blockhash;
123
+ const latestBlockhash = await connection.getLatestBlockhash("confirmed");
124
+ tx.recentBlockhash = latestBlockhash.blockhash;
77
125
  tx.feePayer = payer.publicKey;
78
126
  tx.partialSign(payer);
79
- const sig = await connection.sendRawTransaction(tx.serialize(), {
80
- skipPreflight: true,
81
- preflightCommitment: "confirmed",
82
- maxRetries: options.maxRetries || 3,
83
- });
84
- const shardConfirm = await confirmTransactionRobust(connection, sig, {
85
- commitment: "finalized",
127
+ const shardSend = await sendAndConfirmRawTransactionRobust(connection, tx.serialize(), {
128
+ commitment: bootstrapCommitment,
86
129
  timeoutMs: 120000,
87
130
  debug: options.debug,
131
+ maxRetries: options.maxRetries || 3,
132
+ skipPreflight: false,
133
+ preflightCommitment: "confirmed",
134
+ blockhash: latestBlockhash.blockhash,
135
+ lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
88
136
  });
89
- if (!shardConfirm.success) {
90
- 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"}`);
91
139
  }
92
- signatures.push(sig);
140
+ signatures.push(shardSend.signature);
93
141
  if (options.debug) {
94
142
  console.log(`[FiveSDK] Initialized fee vault shard ${shardIndex}: ${vault.address}`);
95
143
  }
@@ -100,9 +148,6 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
100
148
  Validators.bytecode(bytecode);
101
149
  validator.validateBase58Address(deployer, "deployer");
102
150
  Validators.options(options);
103
- if (options.scriptAccount) {
104
- validator.validateBase58Address(options.scriptAccount, "options.scriptAccount");
105
- }
106
151
  // Resolve program ID with consistent precedence
107
152
  const programId = ProgramIdResolver.resolve(fiveVMProgramId || options.fiveVMProgramId);
108
153
  const exportMetadata = encodeExportMetadata(options.exportMetadata);
@@ -110,7 +155,7 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
110
155
  console.log(`[FiveSDK] Generating deployment transaction (${bytecode.length} bytes)...`);
111
156
  console.log(`[FiveSDK] Using program ID: ${programId}`);
112
157
  }
113
- const scriptResult = await PDAUtils.deriveScriptAccount(bytecode, programId);
158
+ const scriptResult = await resolveScriptAccountDerivation(bytecode, deployer, programId, options);
114
159
  const scriptAccount = scriptResult.address;
115
160
  const scriptSeed = scriptResult.seed;
116
161
  const vmStatePDAResult = await PDAUtils.deriveVMStatePDA(programId);
@@ -119,9 +164,8 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
119
164
  console.log(`[FiveSDK] Script Account: ${scriptAccount} (seed: ${scriptSeed})`);
120
165
  console.log(`[FiveSDK] VM State PDA: ${vmStatePDA}`);
121
166
  }
122
- const SCRIPT_HEADER_SIZE = 64; // ScriptAccountHeader size from Rust program
123
- const totalAccountSize = SCRIPT_HEADER_SIZE + exportMetadata.length + bytecode.length;
124
- 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);
125
169
  const { deployFeeLamports } = await readVMStateFeeConfig(connection, vmStatePDA);
126
170
  const deployShardIndex = 0;
127
171
  const deployVault = await deriveProgramFeeVault(programId, deployShardIndex);
@@ -196,9 +240,8 @@ options = {}) {
196
240
  const scriptKeypair = Keypair.generate();
197
241
  const scriptAccount = scriptKeypair.publicKey.toString();
198
242
  // Calculate account size and rent
199
- const SCRIPT_HEADER_SIZE = 64; // ScriptHeader::LEN
200
243
  const exportMetadata = encodeExportMetadata(options.exportMetadata);
201
- const totalAccountSize = SCRIPT_HEADER_SIZE + exportMetadata.length + bytecode.length;
244
+ const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
202
245
  const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
203
246
  const vmStatePDA = await PDAUtils.deriveVMStatePDA(programIdStr);
204
247
  const vmStatePubkey = new PublicKey(vmStatePDA.address);
@@ -216,7 +259,8 @@ options = {}) {
216
259
  }));
217
260
  }
218
261
  // 1. Initialize canonical VM State if missing
219
- const vmStateInfo = await connection.getAccountInfo(vmStatePubkey, "finalized");
262
+ const bootstrapCommitment = selectBootstrapCommitment(connection);
263
+ const vmStateInfo = await connection.getAccountInfo(vmStatePubkey, bootstrapCommitment);
220
264
  if (!vmStateInfo) {
221
265
  tx.add(new TransactionInstruction({
222
266
  keys: [
@@ -280,17 +324,18 @@ options = {}) {
280
324
  console.log(`[FiveSDK] Generated script keypair: ${scriptAccount}`);
281
325
  }
282
326
  // Calculate account size and rent
283
- const SCRIPT_HEADER_SIZE = 64; // ScriptHeader::LEN (five-protocol)
284
327
  const exportMetadata = encodeExportMetadata(options.exportMetadata);
285
- const totalAccountSize = SCRIPT_HEADER_SIZE + exportMetadata.length + bytecode.length;
328
+ const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
286
329
  const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
287
330
  const vmStateResolution = await ensureCanonicalVmStateAccount(connection, deployerKeypair, new PublicKey(programId), {
288
331
  vmStateAccount: options.vmStateAccount,
289
332
  maxRetries: options.maxRetries,
290
333
  debug: options.debug,
334
+ network: options.network,
291
335
  });
292
336
  const vmStatePubkey = vmStateResolution.vmStatePubkey;
293
337
  const vmStateRent = vmStateResolution.vmStateRent;
338
+ const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
294
339
  const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
295
340
  const deployShardIndex = 0;
296
341
  const deployVault = await deriveProgramFeeVault(programId, deployShardIndex);
@@ -313,7 +358,7 @@ options = {}) {
313
358
  console.log(`[FiveSDK] Export metadata size: ${exportMetadata.length} bytes`);
314
359
  console.log(`[FiveSDK] Rent cost: ${((rentLamports + vmStateRent) / 1e9)} SOL`);
315
360
  }
316
- 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 });
317
362
  // SINGLE TRANSACTION: create script account + deploy bytecode
318
363
  const tx = new Transaction();
319
364
  // Optional compute budget
@@ -378,19 +423,20 @@ options = {}) {
378
423
  if (options.debug) {
379
424
  console.log(`[FiveSDK] Transaction serialized: ${txSerialized.length} bytes`);
380
425
  }
381
- const signature = await connection.sendRawTransaction(txSerialized, {
382
- skipPreflight: true,
383
- preflightCommitment: "confirmed",
426
+ const sendResult = await sendAndConfirmRawTransactionRobust(connection, txSerialized, {
427
+ commitment: "confirmed",
428
+ timeoutMs: 120000,
429
+ debug: options.debug,
384
430
  maxRetries: options.maxRetries || 3,
431
+ skipPreflight: false,
432
+ preflightCommitment: "confirmed",
385
433
  });
434
+ const signature = sendResult.signature;
386
435
  if (options.debug) {
387
436
  console.log(`[FiveSDK] sendRawTransaction completed, returned signature: ${signature}`);
388
437
  }
389
- // Custom confirmation polling with extended timeout (120 seconds)
390
- const confirmationResult = await pollForConfirmation(connection, signature, "confirmed", 120000, // 120 second timeout
391
- options.debug);
392
- if (!confirmationResult.success) {
393
- const errorMessage = `Deployment confirmation failed: ${confirmationResult.error || "Unknown error"}`;
438
+ if (!sendResult.success || !signature) {
439
+ const errorMessage = `Deployment confirmation failed: ${sendResult.error || "Unknown error"}`;
394
440
  if (options.debug)
395
441
  console.log(`[FiveSDK] ${errorMessage}`);
396
442
  return {
@@ -399,8 +445,8 @@ options = {}) {
399
445
  transactionId: signature,
400
446
  };
401
447
  }
402
- if (confirmationResult.err) {
403
- const errorMessage = `Combined deployment failed: ${JSON.stringify(confirmationResult.err)}`;
448
+ if (sendResult.err) {
449
+ const errorMessage = `Combined deployment failed: ${JSON.stringify(sendResult.err)}`;
404
450
  if (options.debug)
405
451
  console.log(`[FiveSDK] ${errorMessage}`);
406
452
  return {
@@ -468,8 +514,7 @@ options = {}) {
468
514
  const scriptKeypair = Keypair.generate();
469
515
  const scriptAccount = scriptKeypair.publicKey.toString();
470
516
  // Calculate account size and rent
471
- const SCRIPT_HEADER_SIZE = 64; // ScriptHeader::LEN (five-protocol)
472
- const totalAccountSize = SCRIPT_HEADER_SIZE + bytecode.length;
517
+ const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
473
518
  const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
474
519
  const programIdStr = ProgramIdResolver.resolve(options.fiveVMProgramId);
475
520
  const programId = new PublicKey(programIdStr);
@@ -477,9 +522,11 @@ options = {}) {
477
522
  vmStateAccount: options.vmStateAccount,
478
523
  maxRetries: options.maxRetries,
479
524
  debug: options.debug,
525
+ network: options.network,
480
526
  });
481
527
  const vmStatePubkey = vmStateResolution.vmStatePubkey;
482
528
  const vmStateRent = vmStateResolution.vmStateRent;
529
+ const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
483
530
  const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
484
531
  const deployShardIndex = 0;
485
532
  const deployVault = await deriveProgramFeeVault(programIdStr, deployShardIndex);
@@ -501,7 +548,7 @@ options = {}) {
501
548
  console.log(`[FiveSDK] Total account size: ${totalAccountSize} bytes`);
502
549
  console.log(`[FiveSDK] Initial rent cost: ${(rentLamports + vmStateRent) / 1e9} SOL`);
503
550
  }
504
- 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 });
505
552
  const transactionIds = [];
506
553
  let totalCost = rentLamports + vmStateRent;
507
554
  // TRANSACTION 1: Create Account + InitLargeProgram
@@ -514,7 +561,7 @@ options = {}) {
514
561
  fromPubkey: deployerKeypair.publicKey,
515
562
  newAccountPubkey: scriptKeypair.publicKey,
516
563
  lamports: rentLamports,
517
- space: SCRIPT_HEADER_SIZE, // Start with just header space
564
+ space: SCRIPT_ACCOUNT_HEADER_LEN, // Start with just the ScriptAccountHeader
518
565
  programId: programId,
519
566
  });
520
567
  initTransaction.add(createAccountInstruction);
@@ -535,7 +582,7 @@ options = {}) {
535
582
  {
536
583
  pubkey: vmStatePubkey,
537
584
  isSigner: false,
538
- isWritable: false,
585
+ isWritable: true,
539
586
  },
540
587
  ...feeVaultKeys,
541
588
  ],
@@ -545,23 +592,24 @@ options = {}) {
545
592
  initTransaction.add(initLargeProgramInstruction);
546
593
  // Sign and send initialization transaction
547
594
  initTransaction.feePayer = deployerKeypair.publicKey;
548
- const { blockhash } = await connection.getLatestBlockhash("confirmed");
549
- initTransaction.recentBlockhash = blockhash;
595
+ const initBlockhash = await connection.getLatestBlockhash("confirmed");
596
+ initTransaction.recentBlockhash = initBlockhash.blockhash;
550
597
  initTransaction.partialSign(deployerKeypair);
551
598
  initTransaction.partialSign(scriptKeypair);
552
- const initSignature = await connection.sendRawTransaction(initTransaction.serialize(), {
553
- skipPreflight: true,
554
- preflightCommitment: "confirmed",
555
- maxRetries: options.maxRetries || 3,
556
- });
557
- const initConfirm = await confirmTransactionRobust(connection, initSignature, {
558
- commitment: "finalized",
599
+ const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
600
+ commitment: bootstrapCommitment,
559
601
  timeoutMs: 120000,
560
602
  debug: options.debug,
603
+ maxRetries: options.maxRetries || 3,
604
+ skipPreflight: false,
605
+ preflightCommitment: "confirmed",
606
+ blockhash: initBlockhash.blockhash,
607
+ lastValidBlockHeight: initBlockhash.lastValidBlockHeight,
561
608
  });
562
- if (!initConfirm.success) {
563
- 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"}`);
564
611
  }
612
+ const initSignature = initSend.signature;
565
613
  transactionIds.push(initSignature);
566
614
  if (options.debug) {
567
615
  console.log(`[FiveSDK] ✅ Initialization completed: ${initSignature}`);
@@ -580,7 +628,7 @@ options = {}) {
580
628
  console.log(`[FiveSDK] Step ${i + 2}: Appending chunk ${i + 1}/${chunks.length} (${chunk.length} bytes)`);
581
629
  }
582
630
  // Calculate additional rent needed for this chunk
583
- 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 });
584
632
  if (!currentInfo)
585
633
  throw new Error("Script account not found after initialization");
586
634
  const newSize = currentInfo.data.length + chunk.length;
@@ -633,7 +681,7 @@ options = {}) {
633
681
  {
634
682
  pubkey: vmStatePubkey,
635
683
  isSigner: false,
636
- isWritable: false,
684
+ isWritable: true,
637
685
  },
638
686
  ...feeVaultKeys,
639
687
  ],
@@ -646,19 +694,20 @@ options = {}) {
646
694
  appendTransaction.feePayer = deployerKeypair.publicKey;
647
695
  appendTransaction.recentBlockhash = appendBlockhash.blockhash;
648
696
  appendTransaction.partialSign(deployerKeypair);
649
- const appendSignature = await connection.sendRawTransaction(appendTransaction.serialize(), {
650
- skipPreflight: true,
651
- preflightCommitment: "confirmed",
652
- maxRetries: options.maxRetries || 3,
653
- });
654
- const appendConfirm = await confirmTransactionRobust(connection, appendSignature, {
655
- commitment: "finalized",
697
+ const appendSend = await sendAndConfirmRawTransactionRobust(connection, appendTransaction.serialize(), {
698
+ commitment: bootstrapCommitment,
656
699
  timeoutMs: 120000,
657
700
  debug: options.debug,
701
+ maxRetries: options.maxRetries || 3,
702
+ skipPreflight: false,
703
+ preflightCommitment: "confirmed",
704
+ blockhash: appendBlockhash.blockhash,
705
+ lastValidBlockHeight: appendBlockhash.lastValidBlockHeight,
658
706
  });
659
- if (!appendConfirm.success) {
660
- 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"}`);
661
709
  }
710
+ const appendSignature = appendSend.signature;
662
711
  transactionIds.push(appendSignature);
663
712
  if (options.debug) {
664
713
  console.log(`[FiveSDK] ✅ Chunk ${i + 1} appended: ${appendSignature}`);
@@ -666,7 +715,7 @@ options = {}) {
666
715
  }
667
716
  // Final verification
668
717
  let finalInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, {
669
- commitment: "finalized",
718
+ commitment: bootstrapCommitment,
670
719
  retries: 2,
671
720
  delayMs: 1000,
672
721
  debug: options.debug,
@@ -674,7 +723,7 @@ options = {}) {
674
723
  if (!finalInfo) {
675
724
  throw new Error("Script account not found during final verification");
676
725
  }
677
- const expectedSize = SCRIPT_HEADER_SIZE + bytecode.length;
726
+ const expectedSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
678
727
  if (options.debug) {
679
728
  console.log(`[FiveSDK] 🔍 Final verification:`);
680
729
  console.log(`[FiveSDK] Expected size: ${expectedSize} bytes`);
@@ -738,8 +787,7 @@ options = {}) {
738
787
  const scriptKeypair = Keypair.generate();
739
788
  const scriptAccount = scriptKeypair.publicKey.toString();
740
789
  // Calculate full account size upfront
741
- const SCRIPT_HEADER_SIZE = 64; // ScriptAccountHeader::LEN
742
- const totalAccountSize = SCRIPT_HEADER_SIZE + bytecode.length;
790
+ const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
743
791
  const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
744
792
  const programIdStr = ProgramIdResolver.resolve(options.fiveVMProgramId);
745
793
  const programId = new PublicKey(programIdStr);
@@ -747,9 +795,11 @@ options = {}) {
747
795
  vmStateAccount: options.vmStateAccount,
748
796
  maxRetries: options.maxRetries,
749
797
  debug: options.debug,
798
+ network: options.network,
750
799
  });
751
800
  const vmStatePubkey = vmStateResolution.vmStatePubkey;
752
801
  const vmStateRent = vmStateResolution.vmStateRent;
802
+ const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
753
803
  const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
754
804
  const deployShardIndex = 0;
755
805
  const deployVault = await deriveProgramFeeVault(programIdStr, deployShardIndex);
@@ -771,7 +821,7 @@ options = {}) {
771
821
  console.log(`[FiveSDK] PRE-ALLOCATED full account size: ${totalAccountSize} bytes`);
772
822
  console.log(`[FiveSDK] Full rent cost paid upfront: ${(rentLamports + vmStateRent) / 1e9} SOL`);
773
823
  }
774
- 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 });
775
825
  const transactionIds = [];
776
826
  let totalCost = rentLamports + vmStateRent;
777
827
  const chunks = chunkBytecode(bytecode, chunkSize);
@@ -808,7 +858,7 @@ options = {}) {
808
858
  {
809
859
  pubkey: vmStatePubkey,
810
860
  isSigner: false,
811
- isWritable: false,
861
+ isWritable: true,
812
862
  },
813
863
  ...feeVaultKeys,
814
864
  ],
@@ -821,19 +871,24 @@ options = {}) {
821
871
  initTransaction.recentBlockhash = blockhash;
822
872
  initTransaction.partialSign(deployerKeypair);
823
873
  initTransaction.partialSign(scriptKeypair);
824
- const initSignature = await connection.sendRawTransaction(initTransaction.serialize(), {
825
- skipPreflight: true,
826
- preflightCommitment: "confirmed",
874
+ const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
875
+ commitment: "confirmed",
876
+ timeoutMs: 120000,
877
+ debug: options.debug,
827
878
  maxRetries: options.maxRetries || 3,
879
+ skipPreflight: false,
880
+ preflightCommitment: "confirmed",
881
+ blockhash: blockhash,
882
+ lastValidBlockHeight: undefined,
828
883
  });
829
- const initConfirmation = await pollForConfirmation(connection, initSignature, "confirmed", 120000, options.debug);
830
- if (!initConfirmation.success) {
884
+ if (!initSend.success || !initSend.signature) {
831
885
  return {
832
886
  success: false,
833
- error: `Initialization confirmation failed: ${initConfirmation.error}`,
887
+ error: `Initialization confirmation failed: ${initSend.error}`,
834
888
  transactionIds
835
889
  };
836
890
  }
891
+ const initSignature = initSend.signature;
837
892
  transactionIds.push(initSignature);
838
893
  if (options.debug) {
839
894
  console.log(`[FiveSDK] ✅ Optimized initialization completed: ${initSignature}`);
@@ -916,19 +971,24 @@ options = {}) {
916
971
  appendTransaction.feePayer = deployerKeypair.publicKey;
917
972
  appendTransaction.recentBlockhash = appendBlockhash.blockhash;
918
973
  appendTransaction.partialSign(deployerKeypair);
919
- const appendSignature = await connection.sendRawTransaction(appendTransaction.serialize(), {
920
- skipPreflight: true,
921
- preflightCommitment: "confirmed",
974
+ const appendSend = await sendAndConfirmRawTransactionRobust(connection, appendTransaction.serialize(), {
975
+ commitment: bootstrapCommitment,
976
+ timeoutMs: 120000,
977
+ debug: options.debug,
922
978
  maxRetries: options.maxRetries || 3,
979
+ skipPreflight: false,
980
+ preflightCommitment: "confirmed",
981
+ blockhash: appendBlockhash.blockhash,
982
+ lastValidBlockHeight: appendBlockhash.lastValidBlockHeight,
923
983
  });
924
- const appendConfirmation = await pollForConfirmation(connection, appendSignature, "finalized", 120000, options.debug);
925
- if (!appendConfirmation.success) {
984
+ if (!appendSend.success || !appendSend.signature) {
926
985
  return {
927
986
  success: false,
928
- error: `Append confirmation failed: ${appendConfirmation.error}`,
987
+ error: `Append confirmation failed: ${appendSend.error}`,
929
988
  transactionIds
930
989
  };
931
990
  }
991
+ const appendSignature = appendSend.signature;
932
992
  transactionIds.push(appendSignature);
933
993
  if (options.debug) {
934
994
  console.log(`[FiveSDK] ✅ Multi-chunk append completed: ${appendSignature}`);
@@ -962,17 +1022,20 @@ options = {}) {
962
1022
  const finalizeBlockhash = await connection.getLatestBlockhash("confirmed");
963
1023
  finalizeTransaction.recentBlockhash = finalizeBlockhash.blockhash;
964
1024
  finalizeTransaction.partialSign(deployerKeypair);
965
- const finalizeSignature = await connection.sendRawTransaction(finalizeTransaction.serialize(), {
966
- skipPreflight: true,
967
- preflightCommitment: "confirmed",
1025
+ const finalizeSend = await sendAndConfirmRawTransactionRobust(connection, finalizeTransaction.serialize(), {
1026
+ commitment: bootstrapCommitment,
1027
+ timeoutMs: 120000,
1028
+ debug: options.debug,
968
1029
  maxRetries: options.maxRetries || 3,
1030
+ skipPreflight: false,
1031
+ preflightCommitment: "confirmed",
1032
+ blockhash: finalizeBlockhash.blockhash,
1033
+ lastValidBlockHeight: finalizeBlockhash.lastValidBlockHeight,
969
1034
  });
970
- // Use custom polling for finalize to handle validator latency
971
- const finalizeConfirmation = await pollForConfirmation(connection, finalizeSignature, "finalized", 120000, // 120 second timeout
972
- options.debug);
973
- if (!finalizeConfirmation.success) {
974
- console.error(`[FiveSDK] FinalizeScript confirmation failed: ${finalizeConfirmation.error}`);
1035
+ if (!finalizeSend.success || !finalizeSend.signature) {
1036
+ console.error(`[FiveSDK] FinalizeScript confirmation failed: ${finalizeSend.error}`);
975
1037
  }
1038
+ const finalizeSignature = finalizeSend.signature;
976
1039
  transactionIds.push(finalizeSignature);
977
1040
  if (options.debug) {
978
1041
  console.log(`[FiveSDK] ✅ FinalizeScript completed: ${finalizeSignature}`);
@@ -1095,7 +1158,8 @@ async function ensureCanonicalVmStateAccount(connection, deployerKeypair, progra
1095
1158
  throw new Error(`vmStateAccount must be canonical PDA ${canonical.address}; got ${options.vmStateAccount}`);
1096
1159
  }
1097
1160
  const vmStatePubkey = new PublicKey(canonical.address);
1098
- const existing = await connection.getAccountInfo(vmStatePubkey, "finalized");
1161
+ const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
1162
+ const existing = await connection.getAccountInfo(vmStatePubkey, bootstrapCommitment);
1099
1163
  if (existing) {
1100
1164
  if (existing.owner.toBase58() !== programId.toBase58()) {
1101
1165
  throw new Error(`canonical VM state ${canonical.address} exists but is owned by ${existing.owner.toBase58()}, expected ${programId.toBase58()}`);
@@ -1125,14 +1189,18 @@ async function ensureCanonicalVmStateAccount(connection, deployerKeypair, progra
1125
1189
  const initBlockhash = await connection.getLatestBlockhash("confirmed");
1126
1190
  initTransaction.recentBlockhash = initBlockhash.blockhash;
1127
1191
  initTransaction.partialSign(deployerKeypair);
1128
- const initSignature = await connection.sendRawTransaction(initTransaction.serialize(), {
1129
- skipPreflight: true,
1130
- preflightCommitment: "confirmed",
1192
+ const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
1193
+ commitment: "confirmed",
1194
+ timeoutMs: 120000,
1195
+ debug: options.debug,
1131
1196
  maxRetries: options.maxRetries || 3,
1197
+ skipPreflight: false,
1198
+ preflightCommitment: "confirmed",
1199
+ blockhash: initBlockhash.blockhash,
1200
+ lastValidBlockHeight: initBlockhash.lastValidBlockHeight,
1132
1201
  });
1133
- const initConfirmation = await pollForConfirmation(connection, initSignature, "confirmed", 120000, options.debug);
1134
- if (!initConfirmation.success || initConfirmation.err) {
1135
- 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)}`);
1136
1204
  }
1137
1205
  return { vmStatePubkey, vmStateRent, created: true, bump: canonical.bump };
1138
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<{