@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
@@ -45,6 +45,7 @@ export interface DiscoveredTest {
45
45
  * Discover tests from directory
46
46
  */
47
47
  export declare class TestDiscovery {
48
+ private static normalizeJsonTestCases;
48
49
  /**
49
50
  * Discover all tests in a directory
50
51
  */
@@ -12,6 +12,16 @@ import { FiveSDK } from '../FiveSDK.js';
12
12
  * Discover tests from directory
13
13
  */
14
14
  export class TestDiscovery {
15
+ static normalizeJsonTestCases(data) {
16
+ const testCases = data.tests || data.testCases || [];
17
+ if (Array.isArray(testCases)) {
18
+ return testCases;
19
+ }
20
+ if (testCases && typeof testCases === 'object') {
21
+ return null;
22
+ }
23
+ return [];
24
+ }
15
25
  /**
16
26
  * Discover all tests in a directory
17
27
  */
@@ -66,7 +76,10 @@ export class TestDiscovery {
66
76
  try {
67
77
  const content = await readFile(file, 'utf8');
68
78
  const data = JSON.parse(content);
69
- const testCases = data.tests || data.testCases || [];
79
+ const testCases = this.normalizeJsonTestCases(data);
80
+ if (testCases === null) {
81
+ continue;
82
+ }
70
83
  for (const testCase of testCases) {
71
84
  tests.push({
72
85
  name: testCase.name,
@@ -98,7 +111,10 @@ export class TestDiscovery {
98
111
  try {
99
112
  const content = await readFile(file, 'utf8');
100
113
  const data = JSON.parse(content);
101
- const testCases = data.tests || data.testCases || [];
114
+ const testCases = this.normalizeJsonTestCases(data);
115
+ if (testCases === null) {
116
+ return [];
117
+ }
102
118
  return testCases.map((testCase) => ({
103
119
  name: testCase.name,
104
120
  path: file,
@@ -211,10 +211,13 @@ export class FiveTestRunner {
211
211
  try {
212
212
  const content = await readFile(test.path, 'utf8');
213
213
  const data = JSON.parse(content);
214
+ const testCases = Array.isArray(data.tests || data.testCases)
215
+ ? (data.tests || data.testCases)
216
+ : [];
214
217
  suites.push({
215
218
  name: data.name || basename(test.path, '.test.json'),
216
219
  description: data.description,
217
- testCases: data.tests || data.testCases || []
220
+ testCases
218
221
  });
219
222
  loadedJsonSuites.add(test.path);
220
223
  }
package/dist/types.d.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  * Type definitions for Five SDK.
3
3
  */
4
4
  export interface ProjectConfig {
5
+ schemaVersion: number;
5
6
  name: string;
6
7
  version: string;
7
8
  description?: string;
@@ -26,13 +27,21 @@ export interface ProjectConfig {
26
27
  export interface ProjectOptimizations {
27
28
  enableCompression?: boolean;
28
29
  enableConstraintOptimization?: boolean;
29
- optimizationLevel?: 'production' | 'development';
30
+ optimizationLevel?: 'production';
30
31
  }
31
32
  export interface ProjectDependency {
32
- name: string;
33
- version: string;
34
- type: 'five' | 'wasm' | 'solana';
33
+ alias: string;
34
+ package: string;
35
+ version?: string;
36
+ source: 'bundled' | 'path' | 'namespace' | 'address' | 'moat';
37
+ link: 'inline' | 'external';
35
38
  path?: string;
39
+ namespace?: string;
40
+ address?: string;
41
+ moatAccount?: string;
42
+ module?: string;
43
+ pin?: string;
44
+ cluster?: string;
36
45
  }
37
46
  export type CompilationTarget = 'vm' | 'solana' | 'debug' | 'test' | 'deployment';
38
47
  export interface CompilationOptions {
@@ -45,7 +54,7 @@ export interface CompilationOptions {
45
54
  /** Enable optimizations */
46
55
  optimize?: boolean;
47
56
  /** Optimization level */
48
- optimizationLevel?: 'production' | 'development';
57
+ optimizationLevel?: 'production';
49
58
  /** Target environment */
50
59
  target?: CompilationTarget;
51
60
  /** Include debug info in bytecode */
@@ -214,6 +223,7 @@ export interface CLIError extends Error {
214
223
  category: string;
215
224
  details?: any;
216
225
  }
226
+ /** @deprecated Use ProgramIdResolver with explicit config or cluster config instead. */
217
227
  export declare const FIVE_VM_PROGRAM_ID = "4Qxf3pbCse2veUgZVMiAm3nWqJrYo2pT4suxHKMJdK1d";
218
228
  export interface FiveSDKConfig {
219
229
  network?: string;
@@ -244,6 +254,7 @@ export interface DeploymentOptions {
244
254
  space?: number;
245
255
  programId?: string;
246
256
  scriptAccount?: any;
257
+ scriptSeed?: string;
247
258
  extraLamports?: number;
248
259
  debug?: boolean;
249
260
  permissions?: number;
package/dist/types.js CHANGED
@@ -2,6 +2,7 @@
2
2
  * Type definitions for Five SDK.
3
3
  */
4
4
  // ==================== Legacy SDK Types (for compatibility) ====================
5
+ /** @deprecated Use ProgramIdResolver with explicit config or cluster config instead. */
5
6
  export const FIVE_VM_PROGRAM_ID = "4Qxf3pbCse2veUgZVMiAm3nWqJrYo2pT4suxHKMJdK1d";
6
7
  export class FiveSDKError extends Error {
7
8
  constructor(message, code, details) {
package/dist/utils/abi.js CHANGED
@@ -13,19 +13,42 @@ export function normalizeAbiFunctions(abiFunctions) {
13
13
  }));
14
14
  return functionsArray
15
15
  .map((func, idx) => {
16
- const parameters = Array.isArray(func.parameters) ? func.parameters : [];
16
+ const rawParameters = Array.isArray(func.parameters) ? func.parameters : [];
17
+ const normalizedParameters = rawParameters.map((param, paramIdx) => ({
18
+ name: param.name ?? `param${paramIdx}`,
19
+ type: param.type ?? param.param_type ?? param.paramType ?? '',
20
+ param_type: param.param_type ?? param.paramType,
21
+ optional: param.optional ?? false,
22
+ is_account: param.is_account ?? param.isAccount ?? false,
23
+ isAccount: param.isAccount ?? param.is_account ?? false,
24
+ attributes: Array.isArray(param.attributes) ? [...param.attributes] : [],
25
+ }));
26
+ const existingParameterNames = new Set(normalizedParameters.map((param) => param.name));
27
+ const accountParameters = Array.isArray(func.accounts)
28
+ ? func.accounts
29
+ .map((account, accountIdx) => {
30
+ const attributes = [];
31
+ if (account?.writable)
32
+ attributes.push('mut');
33
+ if (account?.signer)
34
+ attributes.push('signer');
35
+ return {
36
+ name: account?.name ?? `account${accountIdx}`,
37
+ type: 'pubkey',
38
+ param_type: 'pubkey',
39
+ optional: false,
40
+ is_account: true,
41
+ isAccount: true,
42
+ attributes,
43
+ };
44
+ })
45
+ .filter((param) => !existingParameterNames.has(param.name))
46
+ : [];
47
+ const parameters = [...accountParameters, ...normalizedParameters];
17
48
  return {
18
49
  name: func.name ?? `function_${func.index ?? idx}`,
19
50
  index: typeof func.index === 'number' ? func.index : idx,
20
- parameters: parameters.map((param, paramIdx) => ({
21
- name: param.name ?? `param${paramIdx}`,
22
- type: param.type ?? param.param_type ?? param.paramType ?? '',
23
- param_type: param.param_type ?? param.paramType,
24
- optional: param.optional ?? false,
25
- is_account: param.is_account ?? param.isAccount ?? false,
26
- isAccount: param.isAccount ?? param.is_account ?? false,
27
- attributes: Array.isArray(param.attributes) ? [...param.attributes] : [],
28
- })),
51
+ parameters,
29
52
  returnType: func.returnType ?? func.return_type,
30
53
  accounts: func.accounts ?? [],
31
54
  visibility: func.visibility ??
@@ -19,6 +19,22 @@ export declare function confirmTransactionRobust(connection: any, signature: str
19
19
  err?: any;
20
20
  error?: string;
21
21
  }>;
22
+ export declare function sendAndConfirmRawTransactionRobust(connection: any, serializedTx: Uint8Array | Buffer, options?: {
23
+ commitment?: string;
24
+ timeoutMs?: number;
25
+ debug?: boolean;
26
+ maxRetries?: number;
27
+ skipPreflight?: boolean;
28
+ preflightCommitment?: string;
29
+ resendIntervalMs?: number;
30
+ blockhash?: string;
31
+ lastValidBlockHeight?: number;
32
+ }): Promise<{
33
+ success: boolean;
34
+ signature?: string;
35
+ err?: any;
36
+ error?: string;
37
+ }>;
22
38
  export declare function getAccountInfoWithRetry(connection: any, pubkey: any, options?: {
23
39
  commitment?: string;
24
40
  retries?: number;
@@ -40,12 +40,13 @@ export async function pollForConfirmation(connection, signature, commitment = "c
40
40
  }
41
41
  while (Date.now() - startTime < timeoutMs) {
42
42
  try {
43
- const confirmationStatus = await connection.getSignatureStatus(signature);
43
+ const confirmationStatus = await connection.getSignatureStatuses([signature], { searchTransactionHistory: true });
44
+ const statusValue = confirmationStatus?.value?.[0];
44
45
  if (debug && (Date.now() - startTime) % 10000 < 1000) {
45
- console.log(`[FiveSDK] Confirmation status: ${JSON.stringify(confirmationStatus.value)}`);
46
+ console.log(`[FiveSDK] Confirmation status: ${JSON.stringify(statusValue)}`);
46
47
  }
47
- if (confirmationStatus.value) {
48
- const transactionError = confirmationStatus.value.err;
48
+ if (statusValue) {
49
+ const transactionError = statusValue.err;
49
50
  if (transactionError) {
50
51
  if (debug) {
51
52
  console.log(`[FiveSDK] Transaction error: ${JSON.stringify(transactionError)}`);
@@ -56,7 +57,7 @@ export async function pollForConfirmation(connection, signature, commitment = "c
56
57
  error: JSON.stringify(transactionError),
57
58
  };
58
59
  }
59
- if (statusMeetsCommitment(confirmationStatus.value.confirmationStatus, confirmationStatus.value.confirmations, targetCommitment)) {
60
+ if (statusMeetsCommitment(statusValue.confirmationStatus, statusValue.confirmations, targetCommitment)) {
60
61
  const succeeded = true;
61
62
  if (debug) {
62
63
  console.log(`[FiveSDK] Transaction confirmed after ${Date.now() - startTime}ms${succeeded ? '' : ' (with error)'}`);
@@ -112,6 +113,81 @@ export async function confirmTransactionRobust(connection, signature, options =
112
113
  }
113
114
  return pollForConfirmation(connection, signature, commitment, timeoutMs, debug);
114
115
  }
116
+ export async function sendAndConfirmRawTransactionRobust(connection, serializedTx, options = {}) {
117
+ const commitment = options.commitment || SDK_COMMITMENTS.CONFIRM;
118
+ const timeoutMs = options.timeoutMs || 120000;
119
+ const debug = options.debug || false;
120
+ const resendIntervalMs = options.resendIntervalMs || 1500;
121
+ const targetCommitment = normalizeCommitment(commitment);
122
+ const skipPreflight = options.skipPreflight ?? true;
123
+ const signature = await connection.sendRawTransaction(serializedTx, {
124
+ skipPreflight,
125
+ preflightCommitment: options.preflightCommitment || "confirmed",
126
+ maxRetries: options.maxRetries || 3,
127
+ });
128
+ const startTime = Date.now();
129
+ let lastResendAt = startTime;
130
+ while (Date.now() - startTime < timeoutMs) {
131
+ try {
132
+ const statuses = await connection.getSignatureStatuses([signature], { searchTransactionHistory: true });
133
+ const status = statuses?.value?.[0];
134
+ if (status?.err) {
135
+ return { success: false, signature, err: status.err, error: JSON.stringify(status.err) };
136
+ }
137
+ if (status &&
138
+ statusMeetsCommitment(status.confirmationStatus, status.confirmations, targetCommitment)) {
139
+ return { success: true, signature };
140
+ }
141
+ if (Date.now() - lastResendAt >= resendIntervalMs) {
142
+ try {
143
+ await connection.sendRawTransaction(serializedTx, {
144
+ skipPreflight,
145
+ preflightCommitment: options.preflightCommitment || "confirmed",
146
+ maxRetries: 0,
147
+ });
148
+ if (debug) {
149
+ console.log(`[FiveSDK] Rebroadcasting transaction ${signature}`);
150
+ }
151
+ }
152
+ catch (error) {
153
+ const message = error instanceof Error ? error.message : String(error);
154
+ if (debug &&
155
+ !/already processed|already received|blockhash not found|too old|duplicate/i.test(message)) {
156
+ console.log(`[FiveSDK] Rebroadcast error: ${message}`);
157
+ }
158
+ }
159
+ lastResendAt = Date.now();
160
+ }
161
+ }
162
+ catch (error) {
163
+ if (debug) {
164
+ console.log(`[FiveSDK] send/confirm polling error: ${error instanceof Error ? error.message : String(error)}`);
165
+ }
166
+ }
167
+ if (typeof options.lastValidBlockHeight === "number" &&
168
+ typeof connection.getBlockHeight === "function") {
169
+ try {
170
+ const currentBlockHeight = await connection.getBlockHeight("confirmed");
171
+ if (currentBlockHeight > options.lastValidBlockHeight) {
172
+ return {
173
+ success: false,
174
+ signature,
175
+ error: `Transaction expired before confirmation. Signature: ${signature}`,
176
+ };
177
+ }
178
+ }
179
+ catch {
180
+ // Ignore block height lookup failures and keep polling.
181
+ }
182
+ }
183
+ await sleep(DEFAULT_POLL_INTERVAL_MS);
184
+ }
185
+ return {
186
+ success: false,
187
+ signature,
188
+ error: `Transaction confirmation timeout after ${Date.now() - startTime}ms. Signature: ${signature}`,
189
+ };
190
+ }
115
191
  export async function getAccountInfoWithRetry(connection, pubkey, options = {}) {
116
192
  const commitment = options.commitment || SDK_COMMITMENTS.READ;
117
193
  const retries = options.retries ?? 2;
@@ -18,7 +18,7 @@ export async function compile(ctx, source, options) {
18
18
  const comprehensiveMetrics = options?.comprehensiveMetrics || Boolean(options?.metricsOutput);
19
19
  const compilationOptions = new WasmCompilationOptions()
20
20
  .with_mode(options?.target || "deployment")
21
- .with_optimization_level(options?.optimizationLevel || "production")
21
+ .with_optimization_level("production")
22
22
  .with_v2_preview(true)
23
23
  .with_constraint_cache(false)
24
24
  .with_enhanced_errors(true)
@@ -110,7 +110,7 @@ export async function compileFile(ctx, options) {
110
110
  const comprehensiveMetrics = options.comprehensiveMetrics || Boolean(options.metricsOutput);
111
111
  const compilationOptions = new WasmCompilationOptions()
112
112
  .with_mode(options.target || "deployment")
113
- .with_optimization_level(options.optimizationLevel || "production")
113
+ .with_optimization_level("production")
114
114
  .with_v2_preview(true)
115
115
  .with_constraint_cache(options.enable_constraint_cache !== false)
116
116
  .with_enhanced_errors(true)
@@ -260,7 +260,7 @@ export async function compileWithDiscovery(ctx, entryPoint, options) {
260
260
  const comprehensiveMetrics = options?.comprehensiveMetrics || false;
261
261
  const compilationOptions = new WasmCompilationOptions()
262
262
  .with_mode(options?.target || "deployment")
263
- .with_optimization_level(options?.optimizationLevel || "production")
263
+ .with_optimization_level("production")
264
264
  .with_v2_preview(true)
265
265
  .with_constraint_cache(false)
266
266
  .with_enhanced_errors(true)
package/dist/wasm/vm.d.ts CHANGED
@@ -7,8 +7,8 @@ export declare class FiveVM {
7
7
  initialize(): Promise<void>;
8
8
  private isWasmOnlyExecution;
9
9
  private hasFiveMagic;
10
- private looksLikeScriptHeader;
11
- private looksLikeOptimizedHeader;
10
+ private looksLikeScriptAccountHeader;
11
+ private looksLikeScriptBytecodeHeaderV1;
12
12
  execute(options: VMExecutionOptions): Promise<VMExecutionResult>;
13
13
  private parseVMResult;
14
14
  executeFunction(bytecode: Uint8Array, functionIndex: number, parameters: Array<{
package/dist/wasm/vm.js CHANGED
@@ -1,11 +1,10 @@
1
1
  // Five VM WASM integration.
2
+ import { SCRIPT_ACCOUNT_HEADER_LEN, SCRIPT_BYTECODE_HEADER_V1_LEN, } from '../constants/headers.js';
2
3
  import { getWasmModule } from './loader.js';
3
4
  let FiveVMWasm;
4
5
  let WasmAccount;
5
6
  let ParameterEncoder;
6
7
  let wrap_with_script_header;
7
- const SCRIPT_HEADER_LEN = 64; // ScriptHeader::LEN
8
- const OPTIMIZED_HEADER_LEN = 7; // OptimizedHeader V2 size
9
8
  const FIVE_MAGIC = [0x35, 0x49, 0x56, 0x45];
10
9
  export class FiveVM {
11
10
  constructor(logger) {
@@ -46,21 +45,21 @@ export class FiveVM {
46
45
  return false;
47
46
  return FIVE_MAGIC.every((byte, index) => data[index] === byte);
48
47
  }
49
- looksLikeScriptHeader(data) {
50
- if (data.length < SCRIPT_HEADER_LEN)
48
+ looksLikeScriptAccountHeader(data) {
49
+ if (data.length < SCRIPT_ACCOUNT_HEADER_LEN)
51
50
  return false;
52
51
  if (!this.hasFiveMagic(data))
53
52
  return false;
54
53
  const encodedLen = data[4] + (data[5] << 8) + (data[6] << 16);
55
- const payloadLen = data.length - SCRIPT_HEADER_LEN;
54
+ const payloadLen = data.length - SCRIPT_ACCOUNT_HEADER_LEN;
56
55
  return encodedLen === payloadLen;
57
56
  }
58
- looksLikeOptimizedHeader(data) {
59
- if (data.length < OPTIMIZED_HEADER_LEN)
57
+ looksLikeScriptBytecodeHeaderV1(data) {
58
+ if (data.length < SCRIPT_BYTECODE_HEADER_V1_LEN)
60
59
  return false;
61
60
  if (!this.hasFiveMagic(data))
62
61
  return false;
63
- return !this.looksLikeScriptHeader(data);
62
+ return !this.looksLikeScriptAccountHeader(data);
64
63
  }
65
64
  async execute(options) {
66
65
  if (!this.initialized)
@@ -70,9 +69,9 @@ export class FiveVM {
70
69
  const startTime = Date.now();
71
70
  try {
72
71
  let scriptData;
73
- const hasScriptHeader = this.looksLikeScriptHeader(options.bytecode);
74
- const hasOptimizedHeader = this.looksLikeOptimizedHeader(options.bytecode);
75
- if (hasScriptHeader || hasOptimizedHeader) {
72
+ const hasScriptAccountHeader = this.looksLikeScriptAccountHeader(options.bytecode);
73
+ const hasScriptBytecodeHeaderV1 = this.looksLikeScriptBytecodeHeaderV1(options.bytecode);
74
+ if (hasScriptAccountHeader || hasScriptBytecodeHeaderV1) {
76
75
  scriptData = options.bytecode;
77
76
  }
78
77
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5ive-tech/sdk",
3
- "version": "1.1.12",
3
+ "version": "1.1.14",
4
4
  "description": "Client-agnostic TypeScript SDK for Five VM scripts on Solana",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
File without changes