@5ive-tech/sdk 1.1.2

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 (119) hide show
  1. package/README.md +279 -0
  2. package/dist/FiveSDK.d.ts +336 -0
  3. package/dist/FiveSDK.js +395 -0
  4. package/dist/accounts/index.d.ts +254 -0
  5. package/dist/accounts/index.js +543 -0
  6. package/dist/assets/vm/dummy.file +0 -0
  7. package/dist/assets/vm/five_vm_wasm.d.ts +762 -0
  8. package/dist/assets/vm/five_vm_wasm.js +3754 -0
  9. package/dist/assets/vm/five_vm_wasm_bg.js +3307 -0
  10. package/dist/assets/vm/five_vm_wasm_bg.wasm +0 -0
  11. package/dist/assets/vm/five_vm_wasm_bg.wasm.d.ts +247 -0
  12. package/dist/assets/vm/package.json +11 -0
  13. package/dist/bin/gen-types.d.ts +2 -0
  14. package/dist/bin/gen-types.js +35 -0
  15. package/dist/compiler/BytecodeCompiler.d.ts +83 -0
  16. package/dist/compiler/BytecodeCompiler.js +379 -0
  17. package/dist/config/ConfigManager.d.ts +13 -0
  18. package/dist/config/ConfigManager.js +27 -0
  19. package/dist/config/ProgramIdResolver.d.ts +62 -0
  20. package/dist/config/ProgramIdResolver.js +104 -0
  21. package/dist/crypto/index.d.ts +211 -0
  22. package/dist/crypto/index.js +451 -0
  23. package/dist/encoding/ParameterEncoder.d.ts +31 -0
  24. package/dist/encoding/ParameterEncoder.js +278 -0
  25. package/dist/index.d.ts +21 -0
  26. package/dist/index.js +28 -0
  27. package/dist/lib/bytecode-encoder.d.ts +62 -0
  28. package/dist/lib/bytecode-encoder.js +281 -0
  29. package/dist/logging/index.d.ts +9 -0
  30. package/dist/logging/index.js +10 -0
  31. package/dist/metadata/index.d.ts +213 -0
  32. package/dist/metadata/index.js +296 -0
  33. package/dist/modules/accounts.d.ts +60 -0
  34. package/dist/modules/accounts.js +275 -0
  35. package/dist/modules/deploy.d.ts +90 -0
  36. package/dist/modules/deploy.js +1118 -0
  37. package/dist/modules/execute.d.ts +90 -0
  38. package/dist/modules/execute.js +649 -0
  39. package/dist/modules/fees.d.ts +14 -0
  40. package/dist/modules/fees.js +112 -0
  41. package/dist/modules/namespaces.d.ts +39 -0
  42. package/dist/modules/namespaces.js +190 -0
  43. package/dist/modules/state-diff.d.ts +35 -0
  44. package/dist/modules/state-diff.js +342 -0
  45. package/dist/modules/vm-state.d.ts +7 -0
  46. package/dist/modules/vm-state.js +44 -0
  47. package/dist/program/AccountResolver.d.ts +67 -0
  48. package/dist/program/AccountResolver.js +134 -0
  49. package/dist/program/BorshSchemaGenerator.d.ts +8 -0
  50. package/dist/program/BorshSchemaGenerator.js +57 -0
  51. package/dist/program/FiveProgram.d.ts +144 -0
  52. package/dist/program/FiveProgram.js +282 -0
  53. package/dist/program/FunctionBuilder.d.ts +114 -0
  54. package/dist/program/FunctionBuilder.js +347 -0
  55. package/dist/program/ProgramAccount.d.ts +38 -0
  56. package/dist/program/ProgramAccount.js +170 -0
  57. package/dist/program/TypeGenerator.d.ts +90 -0
  58. package/dist/program/TypeGenerator.js +195 -0
  59. package/dist/program/index.d.ts +24 -0
  60. package/dist/program/index.js +21 -0
  61. package/dist/project/config.d.ts +5 -0
  62. package/dist/project/config.js +33 -0
  63. package/dist/project/toml.d.ts +6 -0
  64. package/dist/project/toml.js +43 -0
  65. package/dist/project/workspace.d.ts +160 -0
  66. package/dist/project/workspace.js +73 -0
  67. package/dist/testing/AccountMetaGenerator.d.ts +121 -0
  68. package/dist/testing/AccountMetaGenerator.js +261 -0
  69. package/dist/testing/AccountTestFixture.d.ts +211 -0
  70. package/dist/testing/AccountTestFixture.js +530 -0
  71. package/dist/testing/OnChainAccountManager.d.ts +81 -0
  72. package/dist/testing/OnChainAccountManager.js +260 -0
  73. package/dist/testing/StateSerializer.d.ts +65 -0
  74. package/dist/testing/StateSerializer.js +330 -0
  75. package/dist/testing/TestDiscovery.d.ts +79 -0
  76. package/dist/testing/TestDiscovery.js +274 -0
  77. package/dist/testing/TestRunner.d.ts +117 -0
  78. package/dist/testing/TestRunner.js +346 -0
  79. package/dist/testing/index.d.ts +14 -0
  80. package/dist/testing/index.js +13 -0
  81. package/dist/types.d.ts +356 -0
  82. package/dist/types.js +32 -0
  83. package/dist/utils/abi.d.ts +31 -0
  84. package/dist/utils/abi.js +92 -0
  85. package/dist/utils/transaction.d.ts +5 -0
  86. package/dist/utils/transaction.js +48 -0
  87. package/dist/validation/InputValidator.d.ts +142 -0
  88. package/dist/validation/InputValidator.js +332 -0
  89. package/dist/validation/index.d.ts +4 -0
  90. package/dist/validation/index.js +4 -0
  91. package/dist/wasm/compiler/AbiLogic.d.ts +4 -0
  92. package/dist/wasm/compiler/AbiLogic.js +37 -0
  93. package/dist/wasm/compiler/AnalysisLogic.d.ts +6 -0
  94. package/dist/wasm/compiler/AnalysisLogic.js +61 -0
  95. package/dist/wasm/compiler/CompilationLogic.d.ts +10 -0
  96. package/dist/wasm/compiler/CompilationLogic.js +431 -0
  97. package/dist/wasm/compiler/FiveCompiler.d.ts +48 -0
  98. package/dist/wasm/compiler/FiveCompiler.js +183 -0
  99. package/dist/wasm/compiler/InfoLogic.d.ts +6 -0
  100. package/dist/wasm/compiler/InfoLogic.js +24 -0
  101. package/dist/wasm/compiler/OptimizationLogic.d.ts +2 -0
  102. package/dist/wasm/compiler/OptimizationLogic.js +13 -0
  103. package/dist/wasm/compiler/ValidationLogic.d.ts +7 -0
  104. package/dist/wasm/compiler/ValidationLogic.js +26 -0
  105. package/dist/wasm/compiler/index.d.ts +2 -0
  106. package/dist/wasm/compiler/index.js +2 -0
  107. package/dist/wasm/compiler/types.d.ts +8 -0
  108. package/dist/wasm/compiler/types.js +1 -0
  109. package/dist/wasm/compiler/utils.d.ts +8 -0
  110. package/dist/wasm/compiler/utils.js +75 -0
  111. package/dist/wasm/index.d.ts +9 -0
  112. package/dist/wasm/index.js +12 -0
  113. package/dist/wasm/instance.d.ts +1 -0
  114. package/dist/wasm/instance.js +26 -0
  115. package/dist/wasm/loader.d.ts +7 -0
  116. package/dist/wasm/loader.js +112 -0
  117. package/dist/wasm/vm.d.ts +33 -0
  118. package/dist/wasm/vm.js +250 -0
  119. package/package.json +59 -0
@@ -0,0 +1,649 @@
1
+ import { FiveSDKError, } from "../types.js";
2
+ import { BytecodeEncoder } from "../lib/bytecode-encoder.js";
3
+ import { PDAUtils, Base58Utils } from "../crypto/index.js";
4
+ import { ScriptMetadataParser } from "../metadata/index.js";
5
+ import { resolveFunctionIndex, normalizeAbiFunctions } from "../utils/abi.js";
6
+ import { validator, Validators } from "../validation/index.js";
7
+ import { calculateExecuteFee } from "./fees.js";
8
+ import { loadWasmVM } from "../wasm/instance.js";
9
+ import { ProgramIdResolver } from "../config/ProgramIdResolver.js";
10
+ // Helper function to initialize ParameterEncoder if needed (though BytecodeEncoder is preferred)
11
+ // Assume BytecodeEncoder handles it or call it if needed.
12
+ // BytecodeEncoder uses WASM module directly via loader.
13
+ export async function execute(compiler, source, functionName, parameters = [], options = {}) {
14
+ const sourceContent = typeof source === 'string' ? source : source.content;
15
+ Validators.sourceCode(sourceContent);
16
+ Validators.functionRef(functionName);
17
+ Validators.parameters(parameters);
18
+ Validators.options(options);
19
+ if (options.debug) {
20
+ console.log(`[FiveSDK] Compile and execute locally: ${functionName}`);
21
+ }
22
+ // Compile the script
23
+ const compilation = await compiler.compile(source, {
24
+ optimize: options.optimize,
25
+ debug: options.debug,
26
+ });
27
+ if (!compilation.success || !compilation.bytecode) {
28
+ return {
29
+ success: false,
30
+ compilationErrors: compilation.errors,
31
+ error: "Compilation failed",
32
+ };
33
+ }
34
+ if (options.debug) {
35
+ console.log(`[FiveSDK] Compilation successful, executing bytecode...`);
36
+ }
37
+ // Execute the compiled bytecode
38
+ const execution = await executeLocally(compilation.bytecode, functionName, parameters, {
39
+ debug: options.debug,
40
+ trace: options.trace,
41
+ computeUnitLimit: options.computeUnitLimit,
42
+ accounts: options.accounts,
43
+ abi: compilation.abi, // Pass ABI from compilation for function name resolution
44
+ });
45
+ return {
46
+ ...execution,
47
+ compilation,
48
+ bytecodeSize: compilation.bytecode.length,
49
+ functions: compilation.metadata?.functions,
50
+ };
51
+ }
52
+ export async function executeLocally(bytecode, functionName, parameters = [], options = {}) {
53
+ Validators.bytecode(bytecode);
54
+ Validators.functionRef(functionName);
55
+ Validators.parameters(parameters);
56
+ Validators.options(options);
57
+ const startTime = Date.now();
58
+ if (options.debug) {
59
+ console.log(`[FiveSDK] Executing locally: function=${functionName}, params=${parameters.length}`);
60
+ console.log(`[FiveSDK] Parameters:`, parameters);
61
+ }
62
+ try {
63
+ const wasmVM = await loadWasmVM();
64
+ let resolvedFunctionIndex;
65
+ if (typeof functionName === "number") {
66
+ resolvedFunctionIndex = functionName;
67
+ }
68
+ else if (options.abi) {
69
+ try {
70
+ resolvedFunctionIndex = resolveFunctionIndex(options.abi, functionName);
71
+ }
72
+ catch (resolutionError) {
73
+ throw new FiveSDKError(`Function name resolution failed: ${resolutionError instanceof Error ? resolutionError.message : "Unknown error"}`, "FUNCTION_RESOLUTION_ERROR");
74
+ }
75
+ }
76
+ else {
77
+ throw new FiveSDKError(`Cannot resolve function name '${functionName}' without ABI information. Please provide function index or use compileAndExecuteLocally() instead.`, "MISSING_ABI_ERROR");
78
+ }
79
+ const transformedParams = parameters.map((param, index) => ({
80
+ type: inferParameterType(param),
81
+ value: param,
82
+ }));
83
+ if (options.debug) {
84
+ console.log(`[FiveSDK] Resolved function index: ${resolvedFunctionIndex}`);
85
+ console.log(`[FiveSDK] Transformed parameters:`, transformedParams);
86
+ }
87
+ let accountInfos = [];
88
+ if (options.accounts && options.accounts.length > 0) {
89
+ accountInfos = options.accounts.map((address, index) => ({
90
+ key: address,
91
+ lamports: 0,
92
+ data: new Uint8Array(0),
93
+ owner: 'TokenkegQfeZyiNwAJsyFbPVwwQQforre5PJNYbToN', // System program default
94
+ isExecutable: false,
95
+ isSigner: index === 0, // First account is signer by default
96
+ isWritable: index === 1, // Second account is mutable by default
97
+ }));
98
+ if (options.debug) {
99
+ console.log(`[FiveSDK] Passing ${accountInfos.length} accounts to WASM VM execution`);
100
+ accountInfos.forEach((acc, i) => {
101
+ console.log(` Account ${i}: ${acc.key.substring(0, 8)}... (signer=${acc.isSigner}, writable=${acc.isWritable})`);
102
+ });
103
+ }
104
+ }
105
+ const result = await wasmVM.executeFunction(bytecode, resolvedFunctionIndex, transformedParams, accountInfos.length > 0 ? accountInfos : undefined);
106
+ const executionTime = Date.now() - startTime;
107
+ if (options.debug) {
108
+ console.log(`[FiveSDK] Local execution ${result.success ? "completed" : "failed"} in ${executionTime}ms`);
109
+ if (result.computeUnitsUsed) {
110
+ console.log(`[FiveSDK] Compute units used: ${result.computeUnitsUsed}`);
111
+ }
112
+ }
113
+ return {
114
+ success: result.success,
115
+ result: result.result,
116
+ logs: result.logs,
117
+ computeUnitsUsed: result.computeUnitsUsed,
118
+ executionTime,
119
+ error: result.error,
120
+ trace: result.trace,
121
+ };
122
+ }
123
+ catch (error) {
124
+ const executionTime = Date.now() - startTime;
125
+ const errorMessage = error instanceof Error ? error.message : "Unknown execution error";
126
+ if (options.debug) {
127
+ console.log(`[FiveSDK] Local execution failed after ${executionTime}ms: ${errorMessage}`);
128
+ }
129
+ return {
130
+ success: false,
131
+ executionTime,
132
+ error: errorMessage,
133
+ };
134
+ }
135
+ }
136
+ export async function generateExecuteInstruction(scriptAccount, functionName, parameters = [], accounts = [], connection, options = {}) {
137
+ validator.validateBase58Address(scriptAccount, "scriptAccount");
138
+ Validators.functionRef(functionName);
139
+ Validators.parameters(parameters);
140
+ Validators.accounts(accounts);
141
+ Validators.options(options);
142
+ if (options.debug) {
143
+ console.log(`[FiveSDK] Generating execution instruction:`, {
144
+ scriptAccount,
145
+ function: functionName,
146
+ parameterCount: parameters.length,
147
+ accountCount: accounts.length,
148
+ });
149
+ }
150
+ let functionIndex;
151
+ let encodedParams;
152
+ let actualParamCount = 0;
153
+ let funcDef = null;
154
+ try {
155
+ let scriptMetadata = options.abi;
156
+ if (!scriptMetadata) {
157
+ // Need to fetch script metadata
158
+ if (connection) {
159
+ const metadata = await ScriptMetadataParser.getScriptMetadata(connection, scriptAccount);
160
+ const normalizedFunctions = normalizeAbiFunctions(metadata.abi?.functions ?? metadata.abi);
161
+ scriptMetadata = {
162
+ functions: normalizedFunctions.map((func) => ({
163
+ name: func.name,
164
+ index: func.index,
165
+ parameters: func.parameters,
166
+ returnType: func.returnType,
167
+ visibility: func.visibility,
168
+ })),
169
+ };
170
+ }
171
+ else {
172
+ throw new Error("No connection provided for metadata retrieval. " +
173
+ "In client-agnostic mode, provide script metadata directly or use getScriptMetadataWithConnection().");
174
+ }
175
+ }
176
+ if (Array.isArray(scriptMetadata.functions)) {
177
+ }
178
+ else if (typeof scriptMetadata.functions === 'object' && scriptMetadata.functions !== null) {
179
+ scriptMetadata.functions = Object.entries(scriptMetadata.functions).map(([name, func]) => ({
180
+ name,
181
+ ...(func || {}),
182
+ }));
183
+ }
184
+ functionIndex =
185
+ typeof functionName === "number"
186
+ ? functionName
187
+ : resolveFunctionIndex(scriptMetadata, functionName);
188
+ funcDef = Array.isArray(scriptMetadata.functions)
189
+ ? scriptMetadata.functions.find((f) => f.index === functionIndex)
190
+ : scriptMetadata.functions[functionIndex];
191
+ const paramDefs = (funcDef.parameters || []);
192
+ actualParamCount = paramDefs.length;
193
+ encodedParams = await encodeParametersWithABI(parameters, funcDef, functionIndex, accounts, options);
194
+ }
195
+ catch (metadataError) {
196
+ if (options.debug) {
197
+ console.log(`[FiveSDK] Metadata not available, using fixed encoding with assumed parameter types`);
198
+ console.log(`[FiveSDK] ABI processing error:`, metadataError);
199
+ }
200
+ functionIndex = typeof functionName === "number" ? functionName : 0;
201
+ const paramDefs = parameters.map((_, index) => ({
202
+ name: `param${index}`,
203
+ type: "u64",
204
+ }));
205
+ const paramValues = {};
206
+ paramDefs.forEach((param, index) => {
207
+ paramValues[param.name] = parameters[index];
208
+ });
209
+ actualParamCount = paramDefs.length;
210
+ encodedParams = await BytecodeEncoder.encodeExecute(functionIndex, paramDefs, paramValues, true, options);
211
+ }
212
+ // Resolve program ID with consistent precedence
213
+ const programId = ProgramIdResolver.resolve(options.fiveVMProgramId);
214
+ const vmStatePDA = await PDAUtils.deriveVMStatePDA(programId);
215
+ const vmState = options.vmStateAccount || vmStatePDA.address;
216
+ let adminAccount = options.adminAccount;
217
+ if (!adminAccount && connection) {
218
+ try {
219
+ let vmStateAddress = options.vmStateAccount;
220
+ if (!vmStateAddress) {
221
+ const pda = await PDAUtils.deriveVMStatePDA(programId);
222
+ vmStateAddress = pda.address;
223
+ }
224
+ const { PublicKey } = await import("@solana/web3.js");
225
+ const info = await connection.getAccountInfo(new PublicKey(vmStateAddress));
226
+ if (info) {
227
+ const data = new Uint8Array(info.data);
228
+ if (data.length >= 32) {
229
+ const authorityPubkey = new PublicKey(data.slice(0, 32));
230
+ adminAccount = authorityPubkey.toBase58();
231
+ }
232
+ }
233
+ }
234
+ catch (error) {
235
+ if (options.debug) {
236
+ console.warn(`[FiveSDK] Failed to resolve admin account from VM state:`, error);
237
+ }
238
+ }
239
+ }
240
+ const instructionAccounts = [
241
+ { pubkey: scriptAccount, isSigner: false, isWritable: false },
242
+ { pubkey: vmState, isSigner: false, isWritable: true },
243
+ ];
244
+ const abiAccountMetadata = new Map();
245
+ if (funcDef && funcDef.parameters) {
246
+ // First pass: detect if there's an @init constraint and find the payer
247
+ let hasInit = false;
248
+ let payerPubkey;
249
+ for (let i = 0; i < funcDef.parameters.length; i++) {
250
+ const param = funcDef.parameters[i];
251
+ if (param.is_account || param.isAccount) {
252
+ const attributes = param.attributes || [];
253
+ if (attributes.includes('init')) {
254
+ hasInit = true;
255
+ for (let j = 0; j < funcDef.parameters.length; j++) {
256
+ const payerParam = funcDef.parameters[j];
257
+ if (i !== j &&
258
+ (payerParam.is_account || payerParam.isAccount) &&
259
+ (payerParam.attributes || []).includes('signer')) {
260
+ const payerValue = parameters[j];
261
+ payerPubkey = payerValue?.toString();
262
+ break;
263
+ }
264
+ }
265
+ break;
266
+ }
267
+ }
268
+ }
269
+ funcDef.parameters.forEach((param, paramIndex) => {
270
+ if (param.is_account || param.isAccount) {
271
+ const value = parameters[paramIndex];
272
+ const pubkey = value?.toString();
273
+ if (pubkey) {
274
+ const attributes = param.attributes || [];
275
+ const isSigner = attributes.includes('signer');
276
+ const isWritable = attributes.includes('mut') ||
277
+ attributes.includes('init') ||
278
+ (hasInit && pubkey === payerPubkey);
279
+ const existing = abiAccountMetadata.get(pubkey) || { isSigner: false, isWritable: false };
280
+ abiAccountMetadata.set(pubkey, {
281
+ isSigner: existing.isSigner || isSigner,
282
+ isWritable: existing.isWritable || isWritable
283
+ });
284
+ }
285
+ }
286
+ });
287
+ }
288
+ const userInstructionAccounts = accounts.map((acc, index) => {
289
+ // Check both derived ABI metadata and passed-in metadata (from FunctionBuilder)
290
+ const abiMetadata = abiAccountMetadata.get(acc);
291
+ const passedMetadata = options.accountMetadata?.get(acc);
292
+ const metadata = abiMetadata || passedMetadata;
293
+ const isSigner = metadata ? metadata.isSigner : (index === 0 && adminAccount ? true : false);
294
+ const isWritable = metadata ? metadata.isWritable : true;
295
+ return {
296
+ pubkey: acc,
297
+ isSigner,
298
+ isWritable
299
+ };
300
+ });
301
+ instructionAccounts.push(...userInstructionAccounts);
302
+ if (adminAccount) {
303
+ const existingAdminIdx = instructionAccounts.findIndex(a => a.pubkey === adminAccount);
304
+ if (existingAdminIdx === -1) {
305
+ instructionAccounts.push({
306
+ pubkey: adminAccount,
307
+ isSigner: false,
308
+ isWritable: true,
309
+ });
310
+ }
311
+ else {
312
+ instructionAccounts[existingAdminIdx].isWritable = true;
313
+ }
314
+ }
315
+ const instructionData = encodeExecuteInstruction(functionIndex, encodedParams, actualParamCount);
316
+ const result = {
317
+ instruction: {
318
+ programId: programId,
319
+ accounts: instructionAccounts,
320
+ data: Buffer.from(instructionData).toString("base64"),
321
+ },
322
+ scriptAccount,
323
+ parameters: {
324
+ function: functionName,
325
+ data: encodedParams,
326
+ count: parameters.length,
327
+ },
328
+ requiredSigners: [],
329
+ estimatedComputeUnits: options.computeUnitLimit ||
330
+ estimateComputeUnits(functionIndex, parameters.length),
331
+ adminAccount: adminAccount,
332
+ };
333
+ const shouldEstimateFees = options.estimateFees !== false && connection;
334
+ if (shouldEstimateFees) {
335
+ try {
336
+ const executeFee = await calculateExecuteFee(connection, programId);
337
+ result.feeInformation = executeFee;
338
+ }
339
+ catch (error) {
340
+ if (options.debug) {
341
+ console.warn(`[FiveSDK] Could not estimate execute fees:`, error instanceof Error ? error.message : "Unknown error");
342
+ }
343
+ }
344
+ }
345
+ return result;
346
+ }
347
+ export async function executeOnSolana(scriptAccount, connection, signerKeypair, functionName, parameters = [], accounts = [], options = {}) {
348
+ let lastSignature;
349
+ try {
350
+ const { PublicKey, Transaction, TransactionInstruction, ComputeBudgetProgram, } = await import("@solana/web3.js");
351
+ let executionData;
352
+ try {
353
+ executionData = await generateExecuteInstruction(scriptAccount, functionName, parameters, accounts, connection, {
354
+ debug: options.debug,
355
+ computeUnitLimit: options.computeUnitLimit,
356
+ vmStateAccount: options.vmStateAccount,
357
+ fiveVMProgramId: options.fiveVMProgramId,
358
+ abi: options.abi,
359
+ });
360
+ }
361
+ catch (metadataError) {
362
+ throw new Error(`Execution instruction generation failed: ${metadataError instanceof Error ? metadataError.message : "Unknown metadata error"}`);
363
+ }
364
+ const transaction = new Transaction();
365
+ if (options.computeUnitLimit && options.computeUnitLimit > 200000) {
366
+ const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({
367
+ units: options.computeUnitLimit,
368
+ });
369
+ transaction.add(computeBudgetIx);
370
+ }
371
+ if (options.computeUnitPrice && options.computeUnitPrice > 0) {
372
+ const computePriceIx = ComputeBudgetProgram.setComputeUnitPrice({
373
+ microLamports: options.computeUnitPrice,
374
+ });
375
+ transaction.add(computePriceIx);
376
+ }
377
+ const accountKeys = [...executionData.instruction.accounts];
378
+ if (options.vmStateAccount && accountKeys.length >= 2) {
379
+ for (let i = 0; i < accountKeys.length; i++) {
380
+ if (i === 1) {
381
+ accountKeys[i].pubkey = options.vmStateAccount;
382
+ break;
383
+ }
384
+ }
385
+ }
386
+ const signerPubkey = signerKeypair.publicKey.toString();
387
+ let signerFound = false;
388
+ for (const meta of accountKeys) {
389
+ if (meta.pubkey === signerPubkey) {
390
+ meta.isSigner = true;
391
+ signerFound = true;
392
+ }
393
+ }
394
+ if (!signerFound) {
395
+ accountKeys.push({
396
+ pubkey: signerPubkey,
397
+ isSigner: true,
398
+ isWritable: true,
399
+ });
400
+ }
401
+ const executeInstruction = new TransactionInstruction({
402
+ keys: accountKeys.map((acc) => ({
403
+ pubkey: new PublicKey(acc.pubkey),
404
+ isSigner: acc.isSigner,
405
+ isWritable: acc.isWritable,
406
+ })),
407
+ programId: new PublicKey(executionData.instruction.programId),
408
+ data: Buffer.from(executionData.instruction.data, "base64"),
409
+ });
410
+ transaction.add(executeInstruction);
411
+ transaction.feePayer = signerKeypair.publicKey;
412
+ const { blockhash } = await connection.getLatestBlockhash("confirmed");
413
+ transaction.recentBlockhash = blockhash;
414
+ transaction.partialSign(signerKeypair);
415
+ const firstSig = transaction.signatures[0]?.signature;
416
+ if (firstSig) {
417
+ lastSignature = Base58Utils.encode(firstSig);
418
+ }
419
+ const signature = await connection.sendRawTransaction(transaction.serialize(), {
420
+ skipPreflight: options.skipPreflight ?? false,
421
+ preflightCommitment: "confirmed",
422
+ maxRetries: options.maxRetries || 3,
423
+ });
424
+ lastSignature = signature;
425
+ let confirmation;
426
+ try {
427
+ confirmation = await connection.confirmTransaction({
428
+ signature,
429
+ blockhash,
430
+ lastValidBlockHeight: (await connection.getLatestBlockhash("confirmed")).lastValidBlockHeight,
431
+ }, "confirmed");
432
+ }
433
+ catch (confirmError) {
434
+ try {
435
+ const txDetails = await connection.getTransaction(signature, {
436
+ commitment: "confirmed",
437
+ maxSupportedTransactionVersion: 0,
438
+ });
439
+ if (txDetails) {
440
+ if (txDetails.meta?.err) {
441
+ return {
442
+ success: false,
443
+ error: `Transaction failed: ${JSON.stringify(txDetails.meta.err)}`,
444
+ logs: txDetails.meta.logMessages || [],
445
+ transactionId: signature,
446
+ };
447
+ }
448
+ else {
449
+ return {
450
+ success: true,
451
+ transactionId: signature,
452
+ computeUnitsUsed: txDetails.meta?.computeUnitsConsumed,
453
+ logs: txDetails.meta?.logMessages || [],
454
+ result: "Execution completed successfully (confirmation timeout but transaction succeeded)",
455
+ };
456
+ }
457
+ }
458
+ }
459
+ catch (getTransactionError) { }
460
+ throw confirmError;
461
+ }
462
+ if (confirmation.value.err) {
463
+ let logs = [];
464
+ let computeUnitsUsed;
465
+ try {
466
+ const txDetails = await connection.getTransaction(signature, {
467
+ commitment: "confirmed",
468
+ maxSupportedTransactionVersion: 0,
469
+ });
470
+ if (txDetails?.meta) {
471
+ logs = txDetails.meta.logMessages || [];
472
+ computeUnitsUsed = txDetails.meta.computeUnitsConsumed || undefined;
473
+ }
474
+ }
475
+ catch { }
476
+ const errorMessage = `Execution transaction failed: ${JSON.stringify(confirmation.value.err)}`;
477
+ return {
478
+ success: false,
479
+ error: errorMessage,
480
+ transactionId: signature,
481
+ logs,
482
+ computeUnitsUsed,
483
+ };
484
+ }
485
+ let computeUnitsUsed;
486
+ let logs = [];
487
+ try {
488
+ const txDetails = await connection.getTransaction(signature, {
489
+ commitment: "confirmed",
490
+ maxSupportedTransactionVersion: 0,
491
+ });
492
+ if (txDetails?.meta) {
493
+ computeUnitsUsed = txDetails.meta.computeUnitsConsumed || undefined;
494
+ logs = txDetails.meta.logMessages || [];
495
+ }
496
+ }
497
+ catch (logError) { }
498
+ return {
499
+ success: true,
500
+ transactionId: signature,
501
+ computeUnitsUsed,
502
+ logs,
503
+ result: "Execution completed successfully",
504
+ };
505
+ }
506
+ catch (error) {
507
+ const errorMessage = error instanceof Error ? error.message : "Unknown execution error";
508
+ if (!lastSignature && error?.signature) {
509
+ lastSignature = error.signature;
510
+ }
511
+ let logs = error?.transactionLogs || [];
512
+ if (typeof error?.getLogs === "function") {
513
+ try {
514
+ const extracted = await error.getLogs();
515
+ if (Array.isArray(extracted)) {
516
+ logs = extracted;
517
+ }
518
+ }
519
+ catch { }
520
+ }
521
+ return {
522
+ success: false,
523
+ error: errorMessage,
524
+ transactionId: lastSignature,
525
+ logs,
526
+ };
527
+ }
528
+ }
529
+ export async function executeScriptAccount(scriptAccount, functionIndex = 0, parameters = [], connection, signerKeypair, options = {}) {
530
+ return executeOnSolana(scriptAccount, connection, signerKeypair, functionIndex, parameters, [], {
531
+ debug: options.debug,
532
+ network: options.network,
533
+ computeUnitLimit: options.computeBudget || 1400000,
534
+ maxRetries: options.maxRetries || 3,
535
+ vmStateAccount: options.vmStateAccount,
536
+ fiveVMProgramId: options.fiveVMProgramId,
537
+ });
538
+ }
539
+ // Helpers
540
+ function encodeExecuteInstruction(functionIndex, encodedParams, paramCount) {
541
+ const parts = [];
542
+ parts.push(new Uint8Array([9]));
543
+ // Function index as fixed u32
544
+ parts.push(encodeU32(functionIndex));
545
+ // Param count as fixed u32
546
+ parts.push(encodeU32(paramCount));
547
+ parts.push(encodedParams);
548
+ const totalLength = parts.reduce((sum, part) => sum + part.length, 0);
549
+ const result = new Uint8Array(totalLength);
550
+ let resultOffset = 0;
551
+ for (const part of parts) {
552
+ result.set(part, resultOffset);
553
+ resultOffset += part.length;
554
+ }
555
+ return result;
556
+ }
557
+ function encodeU32(value) {
558
+ const buffer = new ArrayBuffer(4);
559
+ const view = new DataView(buffer);
560
+ view.setUint32(0, value, true); // Little Endian
561
+ return new Uint8Array(buffer);
562
+ }
563
+ function inferParameterType(value) {
564
+ if (typeof value === "boolean") {
565
+ return "bool";
566
+ }
567
+ else if (typeof value === "number") {
568
+ if (Number.isInteger(value)) {
569
+ return value >= 0 ? "u64" : "i64";
570
+ }
571
+ else {
572
+ return "f64";
573
+ }
574
+ }
575
+ else if (typeof value === "string") {
576
+ return "string";
577
+ }
578
+ else if (value instanceof Uint8Array) {
579
+ return "bytes";
580
+ }
581
+ else {
582
+ return "string";
583
+ }
584
+ }
585
+ async function encodeParametersWithABI(parameters, functionDef, functionIndex, accounts = [], options = {}) {
586
+ const isAccountParam = (param) => {
587
+ if (!param)
588
+ return false;
589
+ if (param.isAccount || param.is_account)
590
+ return true;
591
+ const type = (param.type || param.param_type || '').toString().trim().toLowerCase();
592
+ return type === 'account' || type === 'mint' || type === 'tokenaccount';
593
+ };
594
+ const isPubkeyParam = (param) => {
595
+ if (!param)
596
+ return false;
597
+ const type = (param.type || param.param_type || '').toString().trim().toLowerCase();
598
+ return type === 'pubkey';
599
+ };
600
+ const paramDefs = (functionDef.parameters || []);
601
+ if (parameters.length !== paramDefs.length) {
602
+ console.warn(`[FiveSDK] Parameter validation warning: Function '${functionDef.name}' expects ${paramDefs.length} parameters, but received ${parameters.length}.`);
603
+ }
604
+ const paramValues = {};
605
+ paramDefs.forEach((param, index) => {
606
+ if (index < parameters.length) {
607
+ let value = parameters[index];
608
+ if (isAccountParam(param)) {
609
+ let accountPubkey = null;
610
+ if (value && typeof value === 'object' && typeof value.toBase58 === 'function') {
611
+ accountPubkey = value.toBase58();
612
+ }
613
+ else if (typeof value === 'string') {
614
+ accountPubkey = value;
615
+ }
616
+ else if (typeof value === 'number') {
617
+ if (value >= 0 && value < accounts.length) {
618
+ accountPubkey = accounts[value];
619
+ }
620
+ else {
621
+ throw new Error(`Account index ${value} out of bounds`);
622
+ }
623
+ }
624
+ if (accountPubkey) {
625
+ const accountIndex = accounts.indexOf(accountPubkey);
626
+ if (accountIndex >= 0) {
627
+ // MitoVM receives accounts excluding the script account.
628
+ // Account index 0 is the VM state account.
629
+ value = accountIndex + 1;
630
+ }
631
+ else {
632
+ throw new Error(`Account ${accountPubkey} not found in accounts array`);
633
+ }
634
+ }
635
+ }
636
+ else if (isPubkeyParam(param)) {
637
+ if (value && typeof value === 'object' && typeof value.toBase58 === 'function') {
638
+ value = value.toBase58();
639
+ }
640
+ }
641
+ paramValues[param.name] = value;
642
+ }
643
+ });
644
+ const encoded = await BytecodeEncoder.encodeExecute(functionIndex, paramDefs, paramValues, true, options);
645
+ return encoded;
646
+ }
647
+ function estimateComputeUnits(functionIndex, parameterCount) {
648
+ return Math.max(5000, 1000 + parameterCount * 500 + functionIndex * 100);
649
+ }
@@ -0,0 +1,14 @@
1
+ import { FeeInformation } from "../types.js";
2
+ export declare function getFees(connection: any, fiveVMProgramId?: string): Promise<{
3
+ deployFeeBps: number;
4
+ executeFeeBps: number;
5
+ adminAccount: string | null;
6
+ }>;
7
+ export declare function calculateDeployFee(bytecodeSize: number, connection?: any, fiveVMProgramId?: string): Promise<FeeInformation>;
8
+ export declare function calculateExecuteFee(connection?: any, fiveVMProgramId?: string): Promise<FeeInformation>;
9
+ export declare function getFeeInformation(bytecodeSize: number, connection?: any, fiveVMProgramId?: string): Promise<{
10
+ deploy: FeeInformation;
11
+ execute: FeeInformation;
12
+ adminAccount: string | null;
13
+ feesEnabled: boolean;
14
+ }>;