@5ive-tech/sdk 1.1.10 → 1.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,17 @@
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 { pollForConfirmation } from "../utils/transaction.js";
4
+ import { confirmTransactionRobust, getAccountInfoWithRetry, pollForConfirmation, SDK_COMMITMENTS, } from "../utils/transaction.js";
5
5
  import { ProgramIdResolver } from "../config/ProgramIdResolver.js";
6
- const DEFAULT_FEE_VAULT_SHARD_COUNT = 10;
6
+ import { VmClusterConfigResolver } from "../config/VmClusterConfigResolver.js";
7
+ const DEFAULT_FEE_VAULT_SHARD_COUNT = (() => {
8
+ try {
9
+ return VmClusterConfigResolver.loadClusterConfig().feeVaultShardCount;
10
+ }
11
+ catch {
12
+ return 2;
13
+ }
14
+ })();
7
15
  const FEE_VAULT_NAMESPACE_SEED = Buffer.from([
8
16
  0xff, 0x66, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x6d, 0x5f, 0x66, 0x65, 0x65,
9
17
  0x5f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x31,
@@ -14,7 +22,11 @@ async function readVMStateFeeConfig(connection, vmStateAddress) {
14
22
  }
15
23
  try {
16
24
  const { PublicKey } = await import("@solana/web3.js");
17
- const info = await connection.getAccountInfo(new PublicKey(vmStateAddress), "confirmed");
25
+ const info = await getAccountInfoWithRetry(connection, new PublicKey(vmStateAddress), {
26
+ commitment: SDK_COMMITMENTS.READ,
27
+ retries: 2,
28
+ delayMs: 700,
29
+ });
18
30
  if (!info) {
19
31
  return { shardCount: DEFAULT_FEE_VAULT_SHARD_COUNT };
20
32
  }
@@ -64,7 +76,14 @@ async function initProgramFeeVaultShards(connection, programId, vmStateAccount,
64
76
  preflightCommitment: "confirmed",
65
77
  maxRetries: options.maxRetries || 3,
66
78
  });
67
- await connection.confirmTransaction(sig, "confirmed");
79
+ const shardConfirm = await confirmTransactionRobust(connection, sig, {
80
+ commitment: "finalized",
81
+ timeoutMs: 120000,
82
+ debug: options.debug,
83
+ });
84
+ if (!shardConfirm.success) {
85
+ throw new Error(`Fee vault shard init failed: ${shardConfirm.error || "unconfirmed"}`);
86
+ }
68
87
  signatures.push(sig);
69
88
  if (options.debug) {
70
89
  console.log(`[FiveSDK] Initialized fee vault shard ${shardIndex}: ${vault.address}`);
@@ -192,7 +211,7 @@ options = {}) {
192
211
  }));
193
212
  }
194
213
  // 1. Initialize canonical VM State if missing
195
- const vmStateInfo = await connection.getAccountInfo(vmStatePubkey);
214
+ const vmStateInfo = await connection.getAccountInfo(vmStatePubkey, "finalized");
196
215
  if (!vmStateInfo) {
197
216
  tx.add(new TransactionInstruction({
198
217
  keys: [
@@ -530,7 +549,14 @@ options = {}) {
530
549
  preflightCommitment: "confirmed",
531
550
  maxRetries: options.maxRetries || 3,
532
551
  });
533
- await connection.confirmTransaction(initSignature, "confirmed");
552
+ const initConfirm = await confirmTransactionRobust(connection, initSignature, {
553
+ commitment: "finalized",
554
+ timeoutMs: 120000,
555
+ debug: options.debug,
556
+ });
557
+ if (!initConfirm.success) {
558
+ throw new Error(`Initialization confirmation failed: ${initConfirm.error || "unconfirmed"}`);
559
+ }
534
560
  transactionIds.push(initSignature);
535
561
  if (options.debug) {
536
562
  console.log(`[FiveSDK] ✅ Initialization completed: ${initSignature}`);
@@ -549,16 +575,9 @@ options = {}) {
549
575
  console.log(`[FiveSDK] Step ${i + 2}: Appending chunk ${i + 1}/${chunks.length} (${chunk.length} bytes)`);
550
576
  }
551
577
  // Calculate additional rent needed for this chunk
552
- let currentInfo = await connection.getAccountInfo(scriptKeypair.publicKey);
553
- // Retry logic for account info if null (eventual consistency)
554
- if (!currentInfo) {
555
- if (options.debug)
556
- console.log(`[FiveSDK] Account info null, retrying...`);
557
- await new Promise(resolve => setTimeout(resolve, 1000));
558
- currentInfo = await connection.getAccountInfo(scriptKeypair.publicKey);
559
- if (!currentInfo)
560
- throw new Error("Script account not found after initialization");
561
- }
578
+ const currentInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, { commitment: "finalized", retries: 2, delayMs: 1000, debug: options.debug });
579
+ if (!currentInfo)
580
+ throw new Error("Script account not found after initialization");
562
581
  const newSize = currentInfo.data.length + chunk.length;
563
582
  const newRentRequired = await connection.getMinimumBalanceForRentExemption(newSize);
564
583
  const additionalRent = Math.max(0, newRentRequired - currentInfo.lamports);
@@ -627,14 +646,29 @@ options = {}) {
627
646
  preflightCommitment: "confirmed",
628
647
  maxRetries: options.maxRetries || 3,
629
648
  });
630
- await connection.confirmTransaction(appendSignature, "confirmed");
649
+ const appendConfirm = await confirmTransactionRobust(connection, appendSignature, {
650
+ commitment: "finalized",
651
+ timeoutMs: 120000,
652
+ debug: options.debug,
653
+ });
654
+ if (!appendConfirm.success) {
655
+ throw new Error(`Append confirmation failed: ${appendConfirm.error || "unconfirmed"}`);
656
+ }
631
657
  transactionIds.push(appendSignature);
632
658
  if (options.debug) {
633
659
  console.log(`[FiveSDK] ✅ Chunk ${i + 1} appended: ${appendSignature}`);
634
660
  }
635
661
  }
636
662
  // Final verification
637
- const finalInfo = await connection.getAccountInfo(scriptKeypair.publicKey);
663
+ let finalInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, {
664
+ commitment: "finalized",
665
+ retries: 2,
666
+ delayMs: 1000,
667
+ debug: options.debug,
668
+ });
669
+ if (!finalInfo) {
670
+ throw new Error("Script account not found during final verification");
671
+ }
638
672
  const expectedSize = SCRIPT_HEADER_SIZE + bytecode.length;
639
673
  if (options.debug) {
640
674
  console.log(`[FiveSDK] 🔍 Final verification:`);
@@ -882,7 +916,7 @@ options = {}) {
882
916
  preflightCommitment: "confirmed",
883
917
  maxRetries: options.maxRetries || 3,
884
918
  });
885
- const appendConfirmation = await pollForConfirmation(connection, appendSignature, "confirmed", 120000, options.debug);
919
+ const appendConfirmation = await pollForConfirmation(connection, appendSignature, "finalized", 120000, options.debug);
886
920
  if (!appendConfirmation.success) {
887
921
  return {
888
922
  success: false,
@@ -929,7 +963,7 @@ options = {}) {
929
963
  maxRetries: options.maxRetries || 3,
930
964
  });
931
965
  // Use custom polling for finalize to handle validator latency
932
- const finalizeConfirmation = await pollForConfirmation(connection, finalizeSignature, "confirmed", 120000, // 120 second timeout
966
+ const finalizeConfirmation = await pollForConfirmation(connection, finalizeSignature, "finalized", 120000, // 120 second timeout
933
967
  options.debug);
934
968
  if (!finalizeConfirmation.success) {
935
969
  console.error(`[FiveSDK] FinalizeScript confirmation failed: ${finalizeConfirmation.error}`);
@@ -1056,7 +1090,7 @@ async function ensureCanonicalVmStateAccount(connection, deployerKeypair, progra
1056
1090
  throw new Error(`vmStateAccount must be canonical PDA ${canonical.address}; got ${options.vmStateAccount}`);
1057
1091
  }
1058
1092
  const vmStatePubkey = new PublicKey(canonical.address);
1059
- const existing = await connection.getAccountInfo(vmStatePubkey);
1093
+ const existing = await connection.getAccountInfo(vmStatePubkey, "finalized");
1060
1094
  if (existing) {
1061
1095
  if (existing.owner.toBase58() !== programId.toBase58()) {
1062
1096
  throw new Error(`canonical VM state ${canonical.address} exists but is owned by ${existing.owner.toBase58()}, expected ${programId.toBase58()}`);
@@ -7,7 +7,16 @@ import { validator, Validators } from "../validation/index.js";
7
7
  import { calculateExecuteFee } from "./fees.js";
8
8
  import { loadWasmVM } from "../wasm/instance.js";
9
9
  import { ProgramIdResolver } from "../config/ProgramIdResolver.js";
10
- const DEFAULT_FEE_VAULT_SHARD_COUNT = 10;
10
+ import { VmClusterConfigResolver } from "../config/VmClusterConfigResolver.js";
11
+ import { confirmTransactionRobust, getAccountInfoWithRetry, } from "../utils/transaction.js";
12
+ const DEFAULT_FEE_VAULT_SHARD_COUNT = (() => {
13
+ try {
14
+ return VmClusterConfigResolver.loadClusterConfig().feeVaultShardCount;
15
+ }
16
+ catch {
17
+ return 2;
18
+ }
19
+ })();
11
20
  const FEE_VAULT_NAMESPACE_SEED = Buffer.from([
12
21
  0xff, 0x66, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x6d, 0x5f, 0x66, 0x65, 0x65,
13
22
  0x5f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x31,
@@ -24,7 +33,11 @@ async function readVMStateShardCount(connection, vmStateAddress) {
24
33
  return DEFAULT_FEE_VAULT_SHARD_COUNT;
25
34
  try {
26
35
  const { PublicKey } = await import("@solana/web3.js");
27
- const info = await connection.getAccountInfo(new PublicKey(vmStateAddress), "confirmed");
36
+ const info = await getAccountInfoWithRetry(connection, new PublicKey(vmStateAddress), {
37
+ commitment: "finalized",
38
+ retries: 2,
39
+ delayMs: 1000,
40
+ });
28
41
  if (!info)
29
42
  return DEFAULT_FEE_VAULT_SHARD_COUNT;
30
43
  const data = new Uint8Array(info.data);
@@ -322,7 +335,7 @@ export async function generateExecuteInstruction(scriptAccount, functionName, pa
322
335
  };
323
336
  });
324
337
  instructionAccounts.push(...userInstructionAccounts);
325
- const instructionData = encodeExecuteInstruction(functionIndex, encodedParams, actualParamCount, feeShardIndex, feeVault.bump);
338
+ const instructionData = encodeExecuteInstruction(functionIndex, encodedParams, actualParamCount, feeShardIndex, options.debug === true);
326
339
  // Runtime requires strict tail: [payer, fee_vault, system_program].
327
340
  const signerCandidates = instructionAccounts
328
341
  .filter((acc) => acc.isSigner)
@@ -444,15 +457,15 @@ export async function executeOnSolana(scriptAccount, connection, signerKeypair,
444
457
  maxRetries: options.maxRetries || 3,
445
458
  });
446
459
  lastSignature = signature;
447
- let confirmation;
448
- try {
449
- confirmation = await connection.confirmTransaction({
450
- signature,
451
- blockhash,
452
- lastValidBlockHeight: (await connection.getLatestBlockhash("confirmed")).lastValidBlockHeight,
453
- }, "confirmed");
454
- }
455
- catch (confirmError) {
460
+ const latestBlockhash = await connection.getLatestBlockhash("confirmed");
461
+ const confirmation = await confirmTransactionRobust(connection, signature, {
462
+ commitment: "confirmed",
463
+ timeoutMs: 120000,
464
+ debug: options.debug,
465
+ blockhash,
466
+ lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
467
+ });
468
+ if (!confirmation.success) {
456
469
  try {
457
470
  const txDetails = await connection.getTransaction(signature, {
458
471
  commitment: "confirmed",
@@ -479,9 +492,9 @@ export async function executeOnSolana(scriptAccount, connection, signerKeypair,
479
492
  }
480
493
  }
481
494
  catch (getTransactionError) { }
482
- throw confirmError;
495
+ throw new Error(confirmation.error || "Execution confirmation failed");
483
496
  }
484
- if (confirmation.value.err) {
497
+ if (confirmation.err) {
485
498
  let logs = [];
486
499
  let computeUnitsUsed;
487
500
  try {
@@ -495,7 +508,7 @@ export async function executeOnSolana(scriptAccount, connection, signerKeypair,
495
508
  }
496
509
  }
497
510
  catch { }
498
- const errorMessage = `Execution transaction failed: ${JSON.stringify(confirmation.value.err)}`;
511
+ const errorMessage = `Execution transaction failed: ${JSON.stringify(confirmation.err)}`;
499
512
  return {
500
513
  success: false,
501
514
  error: errorMessage,
@@ -559,14 +572,13 @@ export async function executeScriptAccount(scriptAccount, functionIndex = 0, par
559
572
  });
560
573
  }
561
574
  // Helpers
562
- function encodeExecuteInstruction(functionIndex, encodedParams, paramCount, feeShardIndex, feeVaultBump) {
575
+ function encodeExecuteInstruction(functionIndex, encodedParams, paramCount, feeShardIndex, debug = false) {
563
576
  const parts = [];
564
577
  parts.push(new Uint8Array([9]));
565
578
  parts.push(new Uint8Array([
566
579
  EXECUTE_FEE_HEADER_A,
567
580
  EXECUTE_FEE_HEADER_B,
568
581
  feeShardIndex & 0xff,
569
- feeVaultBump & 0xff,
570
582
  ]));
571
583
  // Function index as fixed u32
572
584
  parts.push(encodeU32(functionIndex));
@@ -580,6 +592,15 @@ function encodeExecuteInstruction(functionIndex, encodedParams, paramCount, feeS
580
592
  result.set(part, resultOffset);
581
593
  resultOffset += part.length;
582
594
  }
595
+ if (debug) {
596
+ const payloadLen = encodedParams.length;
597
+ const previewLen = Math.min(24, result.length);
598
+ const previewHex = Buffer.from(result.subarray(0, previewLen)).toString("hex");
599
+ const legacyVarintLikely = result.length >= 9 &&
600
+ // Legacy varint flow had no fee header and placed varint fields immediately after discriminator.
601
+ !(result[1] === EXECUTE_FEE_HEADER_A && result[2] === EXECUTE_FEE_HEADER_B);
602
+ console.log(`[FiveSDK] Execute wire envelope: discr=${result[0]} fee_header=[${result[1]},${result[2]},${result[3]}] function_index_u32=${functionIndex} param_count_u32=${paramCount} payload_len=${payloadLen} total_len=${result.length} preview_hex=${previewHex}${legacyVarintLikely ? " legacy_varint_suspected=true" : ""}`);
603
+ }
583
604
  return result;
584
605
  }
585
606
  function encodeU32(value) {
@@ -625,21 +646,27 @@ async function encodeParametersWithABI(parameters, functionDef, functionIndex, _
625
646
  const type = (param.type || param.param_type || '').toString().trim().toLowerCase();
626
647
  return type === 'pubkey';
627
648
  };
628
- const paramDefs = (functionDef.parameters || []);
649
+ const paramDefs = functionDef.parameters || [];
629
650
  const nonAccountParamDefs = paramDefs.filter((param) => !isAccountParam(param));
630
- const fullParameterListProvided = parameters.length >= paramDefs.length;
631
- if (fullParameterListProvided && parameters.length !== paramDefs.length) {
632
- console.warn(`[FiveSDK] Parameter validation warning: Function '${functionDef.name}' expects ${paramDefs.length} parameters, but received ${parameters.length}.`);
651
+ const isFullParamList = parameters.length === paramDefs.length;
652
+ const isArgOnlyList = parameters.length === nonAccountParamDefs.length;
653
+ if (!isFullParamList && !isArgOnlyList) {
654
+ console.warn(`[FiveSDK] Parameter validation warning: Function '${functionDef.name}' expects ${paramDefs.length} total params (${nonAccountParamDefs.length} non-account), but received ${parameters.length}.`);
633
655
  }
656
+ // Current VM/compiler contract encodes non-account parameters only.
657
+ // If callers pass full ABI params (accounts + args), normalize to args-only order.
658
+ if (isFullParamList) {
659
+ console.warn(`[FiveSDK] Deprecation: full ABI parameter lists (including account params) are normalized to non-account execute args for '${functionDef.name}'. Pass args-only params to avoid this warning.`);
660
+ }
661
+ const defsForEncoding = nonAccountParamDefs;
634
662
  const paramValues = {};
635
- let argCursor = 0;
636
- for (let index = 0; index < paramDefs.length; index++) {
637
- const param = paramDefs[index];
638
- if (isAccountParam(param)) {
639
- continue;
640
- }
641
- const sourceIndex = fullParameterListProvided ? index : argCursor;
642
- if (sourceIndex >= parameters.length) {
663
+ const paramSourceIndexByName = new Map(paramDefs.map((param, index) => [param.name, index]));
664
+ for (let index = 0; index < defsForEncoding.length; index++) {
665
+ const param = defsForEncoding[index];
666
+ const sourceIndex = isFullParamList
667
+ ? (paramSourceIndexByName.get(param.name) ?? -1)
668
+ : index;
669
+ if (sourceIndex < 0 || sourceIndex >= parameters.length) {
643
670
  throw new Error(`Missing value for parameter: ${param.name}`);
644
671
  }
645
672
  let value = parameters[sourceIndex];
@@ -649,10 +676,9 @@ async function encodeParametersWithABI(parameters, functionDef, functionIndex, _
649
676
  }
650
677
  }
651
678
  paramValues[param.name] = value;
652
- argCursor += 1;
653
679
  }
654
- const encoded = await BytecodeEncoder.encodeExecute(functionIndex, nonAccountParamDefs, paramValues, true, options);
655
- return { encoded, paramCount: nonAccountParamDefs.length };
680
+ const encoded = await BytecodeEncoder.encodeExecute(functionIndex, defsForEncoding, paramValues, true, options);
681
+ return { encoded, paramCount: defsForEncoding.length };
656
682
  }
657
683
  function estimateComputeUnits(functionIndex, parameterCount) {
658
684
  return Math.max(5000, 1000 + parameterCount * 500 + functionIndex * 100);
@@ -1,5 +1,6 @@
1
1
  import { PDAUtils, Base58Utils } from "../crypto/index.js";
2
2
  import { ProgramIdResolver } from "../config/ProgramIdResolver.js";
3
+ import { getAccountInfoWithRetry } from "../utils/transaction.js";
3
4
  export async function getVMState(connection, fiveVMProgramId) {
4
5
  const programId = ProgramIdResolver.resolve(fiveVMProgramId);
5
6
  const vmStatePDA = await PDAUtils.deriveVMStatePDA(programId);
@@ -12,7 +13,11 @@ export async function getVMState(connection, fiveVMProgramId) {
12
13
  pubkey = new PublicKey(vmStatePDA.address);
13
14
  }
14
15
  catch { }
15
- const info = await connection.getAccountInfo(pubkey);
16
+ const info = await getAccountInfoWithRetry(connection, pubkey, {
17
+ commitment: "finalized",
18
+ retries: 2,
19
+ delayMs: 1000,
20
+ });
16
21
  if (!info)
17
22
  throw new Error("VM State account not found");
18
23
  accountData = new Uint8Array(info.data);
@@ -22,7 +22,6 @@ export function parseProjectConfig(parsedToml) {
22
22
  rpcUrl: deploy.rpc_url,
23
23
  programId: deploy.program_id,
24
24
  keypairPath: deploy.keypair_path,
25
- multiFileMode: build.multi_file_mode ?? false,
26
25
  optimizations: {
27
26
  enableCompression: optimizations.enable_compression ?? true,
28
27
  enableConstraintOptimization: optimizations.enable_constraint_optimization ?? true,
@@ -238,9 +238,14 @@ export class FiveTestRunner {
238
238
  byFile.set(test.path, cases);
239
239
  }
240
240
  }
241
+ const moduleNameForFile = (file) => file
242
+ .replace(/\.v$/i, '')
243
+ .split(/[\\/]/)
244
+ .filter(Boolean)
245
+ .join('::');
241
246
  for (const [file, testCases] of byFile.entries()) {
242
247
  suites.push({
243
- name: basename(file, '.v'),
248
+ name: moduleNameForFile(file),
244
249
  description: `Tests from ${file}`,
245
250
  testCases
246
251
  });
package/dist/types.d.ts CHANGED
@@ -18,7 +18,6 @@ export interface ProjectConfig {
18
18
  keypairPath?: string;
19
19
  optimizations?: ProjectOptimizations;
20
20
  dependencies?: ProjectDependency[];
21
- multiFileMode?: boolean;
22
21
  wasm?: {
23
22
  loader?: 'auto' | 'node' | 'bundler';
24
23
  modulePaths?: string[];
@@ -80,12 +79,15 @@ export interface CompilationResult {
80
79
  metadata?: CompilationMetadata;
81
80
  errors?: CompilationError[];
82
81
  warnings?: CompilationWarning[];
82
+ diagnostics?: CompilationError[];
83
83
  disassembly?: string[];
84
84
  metrics?: CompilationMetrics;
85
85
  metricsReport?: CompilationMetricsReport;
86
86
  fiveFile?: FiveCompiledFile;
87
87
  publicFunctionNames?: string[];
88
88
  functionNames?: string[] | FunctionNameEntry[];
89
+ formattedErrorsTerminal?: string;
90
+ formattedErrorsJson?: string;
89
91
  }
90
92
  export interface CompilationMetadata {
91
93
  sourceFile: string;
@@ -113,7 +115,16 @@ export interface CompilationError {
113
115
  category?: string;
114
116
  description?: string;
115
117
  location?: any;
116
- suggestions?: string[];
118
+ suggestions?: Array<string | {
119
+ message: string;
120
+ explanation?: string;
121
+ confidence?: number;
122
+ codeSuggestion?: string;
123
+ }>;
124
+ sourceLine?: string;
125
+ sourceSnippet?: string;
126
+ rendered?: string;
127
+ raw?: any;
117
128
  }
118
129
  export interface CompilationWarning {
119
130
  type: string;
@@ -332,12 +343,18 @@ export interface FiveCompiledFile {
332
343
  }
333
344
  export interface FiveFunction {
334
345
  name: string;
346
+ index?: number;
335
347
  parameters: FiveParameter[];
336
348
  returnType?: FiveType;
337
349
  }
338
350
  export interface FiveParameter {
339
351
  name: string;
340
352
  type: FiveType;
353
+ param_type?: FiveType;
354
+ optional?: boolean;
355
+ is_account?: boolean;
356
+ isAccount?: boolean;
357
+ attributes?: string[];
341
358
  }
342
359
  export type FiveType = string;
343
360
  export interface FunctionNameEntry {
@@ -4,7 +4,11 @@ export interface NormalizedABIFunction {
4
4
  parameters: Array<{
5
5
  name: string;
6
6
  type: string;
7
+ param_type?: string;
7
8
  optional?: boolean;
9
+ is_account?: boolean;
10
+ isAccount?: boolean;
11
+ attributes?: string[];
8
12
  }>;
9
13
  returnType?: string;
10
14
  accounts?: any[];
package/dist/utils/abi.js CHANGED
@@ -20,8 +20,11 @@ export function normalizeAbiFunctions(abiFunctions) {
20
20
  parameters: parameters.map((param, paramIdx) => ({
21
21
  name: param.name ?? `param${paramIdx}`,
22
22
  type: param.type ?? param.param_type ?? param.paramType ?? '',
23
+ param_type: param.param_type ?? param.paramType,
23
24
  optional: param.optional ?? false,
25
+ is_account: param.is_account ?? param.isAccount ?? false,
24
26
  isAccount: param.isAccount ?? param.is_account ?? false,
27
+ attributes: Array.isArray(param.attributes) ? [...param.attributes] : [],
25
28
  })),
26
29
  returnType: func.returnType ?? func.return_type,
27
30
  accounts: func.accounts ?? [],
@@ -1,5 +1,27 @@
1
+ export declare const SDK_COMMITMENTS: {
2
+ readonly WRITE: "confirmed";
3
+ readonly READ: "finalized";
4
+ readonly CONFIRM: "finalized";
5
+ };
1
6
  export declare function pollForConfirmation(connection: any, signature: string, commitment?: string, timeoutMs?: number, debug?: boolean): Promise<{
2
7
  success: boolean;
3
8
  err?: any;
4
9
  error?: string;
5
10
  }>;
11
+ export declare function confirmTransactionRobust(connection: any, signature: string, options?: {
12
+ commitment?: string;
13
+ timeoutMs?: number;
14
+ debug?: boolean;
15
+ blockhash?: string;
16
+ lastValidBlockHeight?: number;
17
+ }): Promise<{
18
+ success: boolean;
19
+ err?: any;
20
+ error?: string;
21
+ }>;
22
+ export declare function getAccountInfoWithRetry(connection: any, pubkey: any, options?: {
23
+ commitment?: string;
24
+ retries?: number;
25
+ delayMs?: number;
26
+ debug?: boolean;
27
+ }): Promise<any | null>;
@@ -1,6 +1,40 @@
1
+ export const SDK_COMMITMENTS = {
2
+ WRITE: "confirmed",
3
+ READ: "finalized",
4
+ CONFIRM: "finalized",
5
+ };
6
+ const DEFAULT_POLL_INTERVAL_MS = 1000;
7
+ const DEFAULT_RETRY_DELAY_MS = 700;
8
+ async function sleep(ms) {
9
+ await new Promise(resolve => setTimeout(resolve, ms));
10
+ }
11
+ function backoffDelayMs(baseMs, attempt) {
12
+ const exp = Math.min(attempt, 6);
13
+ const raw = baseMs * (2 ** exp);
14
+ const jitter = Math.floor(raw * (0.15 * Math.random()));
15
+ return raw + jitter;
16
+ }
17
+ function normalizeCommitment(commitment) {
18
+ if (commitment === "finalized")
19
+ return "finalized";
20
+ if (commitment === "processed")
21
+ return "processed";
22
+ return "confirmed";
23
+ }
24
+ function statusMeetsCommitment(status, confirmations, target) {
25
+ if (target === "processed") {
26
+ return !!status || (confirmations ?? 0) >= 0;
27
+ }
28
+ if (target === "confirmed") {
29
+ return status === "confirmed" || status === "finalized" || (confirmations ?? 0) >= 1;
30
+ }
31
+ // finalized must be explicitly finalized; confirmations count is insufficient.
32
+ return status === "finalized";
33
+ }
1
34
  export async function pollForConfirmation(connection, signature, commitment = "confirmed", timeoutMs = 120000, debug = false) {
2
35
  const startTime = Date.now();
3
- const pollIntervalMs = 1000;
36
+ const pollIntervalMs = DEFAULT_POLL_INTERVAL_MS;
37
+ const targetCommitment = normalizeCommitment(commitment);
4
38
  if (debug) {
5
39
  console.log(`[FiveSDK] Starting confirmation poll with ${timeoutMs}ms timeout`);
6
40
  }
@@ -11,30 +45,36 @@ export async function pollForConfirmation(connection, signature, commitment = "c
11
45
  console.log(`[FiveSDK] Confirmation status: ${JSON.stringify(confirmationStatus.value)}`);
12
46
  }
13
47
  if (confirmationStatus.value) {
14
- if (confirmationStatus.value.confirmationStatus === commitment ||
15
- confirmationStatus.value.confirmations >= 1) {
16
- const transactionError = confirmationStatus.value.err;
17
- const succeeded = !transactionError;
48
+ const transactionError = confirmationStatus.value.err;
49
+ if (transactionError) {
50
+ if (debug) {
51
+ console.log(`[FiveSDK] Transaction error: ${JSON.stringify(transactionError)}`);
52
+ }
53
+ return {
54
+ success: false,
55
+ err: transactionError,
56
+ error: JSON.stringify(transactionError),
57
+ };
58
+ }
59
+ if (statusMeetsCommitment(confirmationStatus.value.confirmationStatus, confirmationStatus.value.confirmations, targetCommitment)) {
60
+ const succeeded = true;
18
61
  if (debug) {
19
62
  console.log(`[FiveSDK] Transaction confirmed after ${Date.now() - startTime}ms${succeeded ? '' : ' (with error)'}`);
20
- if (transactionError) {
21
- console.log(`[FiveSDK] Transaction error: ${JSON.stringify(transactionError)}`);
22
- }
23
63
  }
24
64
  return {
25
65
  success: succeeded,
26
- err: transactionError,
27
- error: transactionError ? JSON.stringify(transactionError) : undefined,
66
+ err: undefined,
67
+ error: undefined,
28
68
  };
29
69
  }
30
70
  }
31
- await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
71
+ await sleep(pollIntervalMs);
32
72
  }
33
73
  catch (error) {
34
74
  if (debug) {
35
75
  console.log(`[FiveSDK] Polling error: ${error instanceof Error ? error.message : String(error)}`);
36
76
  }
37
- await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
77
+ await sleep(pollIntervalMs);
38
78
  }
39
79
  }
40
80
  const elapsed = Date.now() - startTime;
@@ -46,3 +86,45 @@ export async function pollForConfirmation(connection, signature, commitment = "c
46
86
  error: `Transaction confirmation timeout after ${elapsed}ms. Signature: ${signature}`,
47
87
  };
48
88
  }
89
+ export async function confirmTransactionRobust(connection, signature, options = {}) {
90
+ const commitment = options.commitment || SDK_COMMITMENTS.CONFIRM;
91
+ const timeoutMs = options.timeoutMs || 120000;
92
+ const debug = options.debug || false;
93
+ try {
94
+ const confirmArg = options.blockhash && typeof options.lastValidBlockHeight === "number"
95
+ ? {
96
+ signature,
97
+ blockhash: options.blockhash,
98
+ lastValidBlockHeight: options.lastValidBlockHeight,
99
+ }
100
+ : signature;
101
+ const confirmation = await connection.confirmTransaction(confirmArg, commitment);
102
+ const err = confirmation?.value?.err;
103
+ if (!err) {
104
+ return { success: true };
105
+ }
106
+ return { success: false, err, error: JSON.stringify(err) };
107
+ }
108
+ catch (error) {
109
+ if (debug) {
110
+ console.log(`[FiveSDK] confirmTransaction threw, falling back to polling: ${error instanceof Error ? error.message : String(error)}`);
111
+ }
112
+ }
113
+ return pollForConfirmation(connection, signature, commitment, timeoutMs, debug);
114
+ }
115
+ export async function getAccountInfoWithRetry(connection, pubkey, options = {}) {
116
+ const commitment = options.commitment || SDK_COMMITMENTS.READ;
117
+ const retries = options.retries ?? 2;
118
+ const delayMs = options.delayMs ?? DEFAULT_RETRY_DELAY_MS;
119
+ const debug = options.debug || false;
120
+ let info = await connection.getAccountInfo(pubkey, commitment);
121
+ for (let attempt = 0; !info && attempt < retries; attempt++) {
122
+ const waitMs = backoffDelayMs(delayMs, attempt);
123
+ if (debug) {
124
+ console.log(`[FiveSDK] getAccountInfo retry ${attempt + 1}/${retries}, waiting ${waitMs}ms`);
125
+ }
126
+ await sleep(waitMs);
127
+ info = await connection.getAccountInfo(pubkey, commitment);
128
+ }
129
+ return info;
130
+ }
@@ -1,10 +1,5 @@
1
1
  import { CompilationOptions, CompilationResult } from "../../types.js";
2
2
  import { CompilationContext } from "./types.js";
3
3
  export declare function compile(ctx: CompilationContext, source: string, options?: any): Promise<any>;
4
- export declare function compileModules(ctx: CompilationContext, mainSource: string, modules: Array<{
5
- name: string;
6
- source: string;
7
- }>, options?: any): Promise<any>;
8
4
  export declare function compileFile(ctx: CompilationContext, options: CompilationOptions): Promise<CompilationResult>;
9
5
  export declare function compileWithDiscovery(ctx: CompilationContext, entryPoint: string, options?: any): Promise<any>;
10
- export declare function compileModulesExplicit(ctx: CompilationContext, moduleFiles: string[], entryPoint: string, options?: any): Promise<any>;