@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,278 @@
1
+ // Parameter encoding for Five VM.
2
+ import { ParameterEncodingError } from '../types.js';
3
+ // Type ID mapping (matches Five VM protocol).
4
+ const TYPE_IDS = {
5
+ 'u8': 1,
6
+ 'u16': 2,
7
+ 'u32': 3,
8
+ 'u64': 4,
9
+ 'i8': 5,
10
+ 'i16': 6,
11
+ 'i32': 7,
12
+ 'i64': 8,
13
+ 'bool': 9,
14
+ 'string': 11,
15
+ 'pubkey': 10,
16
+ 'bytes': 12,
17
+ 'array': 13
18
+ };
19
+ export class ParameterEncoder {
20
+ constructor(debug = false) {
21
+ this.debug = debug;
22
+ if (this.debug) {
23
+ console.log('[ParameterEncoder] Initialized');
24
+ }
25
+ }
26
+ // ==================== Pure Parameter Encoding ====================
27
+ async encodeParameterData(parameters = [], functionSignature) {
28
+ if (this.debug) {
29
+ console.log(`[ParameterEncoder] Encoding parameter data: params=${parameters.length}`);
30
+ }
31
+ const encodedData = await this.encodeParametersInternal(parameters, functionSignature);
32
+ if (this.debug) {
33
+ console.log(`[ParameterEncoder] Encoded parameters: ${encodedData.length} bytes, hex: ${encodedData.toString('hex')}`);
34
+ }
35
+ return encodedData;
36
+ }
37
+ encodeParametersWithABI(parameters, functionSignature, options = {}) {
38
+ if (this.debug) {
39
+ console.log(`[ParameterEncoder] Encoding ${parameters.length} parameters with ABI guidance`);
40
+ }
41
+ const encoded = [];
42
+ for (let i = 0; i < parameters.length; i++) {
43
+ const value = parameters[i];
44
+ const paramDef = functionSignature.parameters[i];
45
+ if (!paramDef && options.strict) {
46
+ throw new ParameterEncodingError(`Parameter ${i} provided but function only expects ${functionSignature.parameters.length} parameters`, { functionName: functionSignature.name, parameterIndex: i });
47
+ }
48
+ // Use ABI type if available, otherwise infer
49
+ const targetType = paramDef?.type || this.inferType(value);
50
+ const encodedParam = this.encodeParameter(value, targetType, i);
51
+ encoded.push(encodedParam);
52
+ }
53
+ if (this.debug) {
54
+ console.log(`[ParameterEncoder] Encoded ${encoded.length} parameters successfully`);
55
+ }
56
+ return encoded;
57
+ }
58
+ // ==================== Type Coercion ====================
59
+ /// Coerce value to a Five VM type.
60
+ coerceValue(value, targetType) {
61
+ if (this.debug) {
62
+ console.log(`[ParameterEncoder] Coercing value ${JSON.stringify(value)} to ${targetType}`);
63
+ }
64
+ try {
65
+ switch (targetType) {
66
+ case 'u8':
67
+ return this.coerceToU8(value);
68
+ case 'u16':
69
+ return this.coerceToU16(value);
70
+ case 'u32':
71
+ return this.coerceToU32(value);
72
+ case 'u64':
73
+ return this.coerceToU64(value);
74
+ case 'i8':
75
+ return this.coerceToI8(value);
76
+ case 'i16':
77
+ return this.coerceToI16(value);
78
+ case 'i32':
79
+ return this.coerceToI32(value);
80
+ case 'i64':
81
+ return this.coerceToI64(value);
82
+ case 'bool':
83
+ return this.coerceToBool(value);
84
+ case 'string':
85
+ return this.coerceToString(value);
86
+ case 'pubkey':
87
+ return this.coerceToPubkey(value);
88
+ case 'bytes':
89
+ return this.coerceToBytes(value);
90
+ case 'array':
91
+ return this.coerceToArray(value);
92
+ default:
93
+ throw new Error(`Unsupported type: ${targetType}`);
94
+ }
95
+ }
96
+ catch (error) {
97
+ throw new ParameterEncodingError(`Failed to coerce value ${JSON.stringify(value)} to ${targetType}: ${error instanceof Error ? error.message : 'Unknown error'}`, { value, targetType });
98
+ }
99
+ }
100
+ // ==================== Private Methods ====================
101
+ /// Use BytecodeEncoder for parameter data only.
102
+ async encodeParametersInternal(parameters, functionSignature) {
103
+ try {
104
+ // Import BytecodeEncoder
105
+ const { BytecodeEncoder } = await import('../lib/bytecode-encoder.js');
106
+ // Convert parameters to format expected by encoder
107
+ const params = parameters.map((value, index) => {
108
+ const paramDef = functionSignature?.parameters[index];
109
+ return {
110
+ name: paramDef?.name || `param_${index}`,
111
+ type: paramDef?.type || this.inferTypeString(value)
112
+ };
113
+ });
114
+ const values = {};
115
+ params.forEach((param, index) => {
116
+ values[param.name] = parameters[index];
117
+ });
118
+ // Encode parameters only; function index is handled by the SDK when building instruction data
119
+ const encoded = await BytecodeEncoder.encodeExecute(0, params, values);
120
+ return Buffer.from(encoded);
121
+ }
122
+ catch (error) {
123
+ throw new Error(`Parameter encoding failed: ${error instanceof Error ? error.message : String(error)}`);
124
+ }
125
+ }
126
+ /// Encode individual parameter.
127
+ encodeParameter(value, type, index) {
128
+ const coercedValue = this.coerceValue(value, type);
129
+ const typeId = TYPE_IDS[type];
130
+ return {
131
+ type: typeId,
132
+ value: coercedValue
133
+ };
134
+ }
135
+ /**
136
+ * Infer Five VM type from JavaScript value
137
+ */
138
+ inferType(value) {
139
+ if (typeof value === 'boolean') {
140
+ return 'bool';
141
+ }
142
+ if (typeof value === 'string') {
143
+ return 'string';
144
+ }
145
+ if (typeof value === 'number') {
146
+ // Default to u64 for positive integers, i64 for negative
147
+ return Number.isInteger(value) && value >= 0 ? 'u64' : 'i64';
148
+ }
149
+ if (typeof value === 'bigint') {
150
+ return value >= 0 ? 'u64' : 'i64';
151
+ }
152
+ if (Array.isArray(value)) {
153
+ return 'array';
154
+ }
155
+ return 'string'; // Default fallback
156
+ }
157
+ /**
158
+ * Infer type as string
159
+ */
160
+ inferTypeString(value) {
161
+ const type = this.inferType(value);
162
+ return type;
163
+ }
164
+ // ==================== Type Coercion Methods ====================
165
+ coerceToU8(value) {
166
+ const num = Number(value);
167
+ if (!Number.isInteger(num) || num < 0 || num > 255) {
168
+ throw new Error(`Value ${value} cannot be coerced to u8 (0-255)`);
169
+ }
170
+ return num;
171
+ }
172
+ coerceToU16(value) {
173
+ const num = Number(value);
174
+ if (!Number.isInteger(num) || num < 0 || num > 65535) {
175
+ throw new Error(`Value ${value} cannot be coerced to u16 (0-65535)`);
176
+ }
177
+ return num;
178
+ }
179
+ coerceToU32(value) {
180
+ const num = Number(value);
181
+ if (!Number.isInteger(num) || num < 0 || num > 4294967295) {
182
+ throw new Error(`Value ${value} cannot be coerced to u32 (0-4294967295)`);
183
+ }
184
+ return num;
185
+ }
186
+ coerceToU64(value) {
187
+ if (typeof value === 'bigint') {
188
+ if (value < BigInt(0) || value > BigInt('18446744073709551615')) {
189
+ throw new Error(`Value ${value} cannot be coerced to u64 (0-2^64-1)`);
190
+ }
191
+ return value;
192
+ }
193
+ const num = Number(value);
194
+ if (!Number.isInteger(num) || num < 0) {
195
+ throw new Error(`Value ${value} cannot be coerced to u64`);
196
+ }
197
+ return num;
198
+ }
199
+ coerceToI8(value) {
200
+ const num = Number(value);
201
+ if (!Number.isInteger(num) || num < -128 || num > 127) {
202
+ throw new Error(`Value ${value} cannot be coerced to i8 (-128 to 127)`);
203
+ }
204
+ return num;
205
+ }
206
+ coerceToI16(value) {
207
+ const num = Number(value);
208
+ if (!Number.isInteger(num) || num < -32768 || num > 32767) {
209
+ throw new Error(`Value ${value} cannot be coerced to i16 (-32768 to 32767)`);
210
+ }
211
+ return num;
212
+ }
213
+ coerceToI32(value) {
214
+ const num = Number(value);
215
+ if (!Number.isInteger(num) || num < -2147483648 || num > 2147483647) {
216
+ throw new Error(`Value ${value} cannot be coerced to i32 (-2^31 to 2^31-1)`);
217
+ }
218
+ return num;
219
+ }
220
+ coerceToI64(value) {
221
+ if (typeof value === 'bigint') {
222
+ if (value < BigInt('-9223372036854775808') || value > BigInt('9223372036854775807')) {
223
+ throw new Error(`Value ${value} cannot be coerced to i64 (-2^63 to 2^63-1)`);
224
+ }
225
+ return value;
226
+ }
227
+ const num = Number(value);
228
+ if (!Number.isInteger(num)) {
229
+ throw new Error(`Value ${value} cannot be coerced to i64`);
230
+ }
231
+ return num;
232
+ }
233
+ coerceToBool(value) {
234
+ if (typeof value === 'boolean') {
235
+ return value;
236
+ }
237
+ if (typeof value === 'string') {
238
+ const lower = value.toLowerCase();
239
+ if (lower === 'true' || lower === '1')
240
+ return true;
241
+ if (lower === 'false' || lower === '0')
242
+ return false;
243
+ throw new Error(`String "${value}" cannot be coerced to boolean`);
244
+ }
245
+ if (typeof value === 'number') {
246
+ return value !== 0;
247
+ }
248
+ throw new Error(`Value ${value} cannot be coerced to boolean`);
249
+ }
250
+ coerceToString(value) {
251
+ return String(value);
252
+ }
253
+ coerceToPubkey(value) {
254
+ if (typeof value === 'string' && value.length === 44) {
255
+ return value; // Assume base58 encoded pubkey
256
+ }
257
+ throw new Error(`Value ${value} cannot be coerced to pubkey`);
258
+ }
259
+ coerceToBytes(value) {
260
+ if (value instanceof Uint8Array) {
261
+ return value;
262
+ }
263
+ if (Array.isArray(value)) {
264
+ return new Uint8Array(value);
265
+ }
266
+ if (typeof value === 'string') {
267
+ // Assume hex string
268
+ return new Uint8Array(Buffer.from(value, 'hex'));
269
+ }
270
+ throw new Error(`Value ${value} cannot be coerced to bytes`);
271
+ }
272
+ coerceToArray(value) {
273
+ if (Array.isArray(value)) {
274
+ return value;
275
+ }
276
+ throw new Error(`Value ${value} cannot be coerced to array`);
277
+ }
278
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Five SDK - Client-Agnostic TypeScript/JavaScript library for Five VM
3
+ *
4
+ * Minimal build for Frontend integration.
5
+ */
6
+ export * from './FiveSDK.js';
7
+ export * from './types.js';
8
+ export * from './lib/bytecode-encoder.js';
9
+ export * from './encoding/ParameterEncoder.js';
10
+ export * from './crypto/index.js';
11
+ export * from './project/toml.js';
12
+ export * from './project/config.js';
13
+ export * from './project/workspace.js';
14
+ export * from './wasm/vm.js';
15
+ export * from './wasm/compiler/index.js';
16
+ export * from './wasm/loader.js';
17
+ export * from './testing/index.js';
18
+ export * from './program/index.js';
19
+ export * from './modules/namespaces.js';
20
+ export { ProgramIdResolver, FIVE_BAKED_PROGRAM_ID } from './config/ProgramIdResolver.js';
21
+ export { FIVE_VM_PROGRAM_ID } from './types.js';
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Five SDK - Client-Agnostic TypeScript/JavaScript library for Five VM
3
+ *
4
+ * Minimal build for Frontend integration.
5
+ */
6
+ // ==================== Core SDK Exports ====================
7
+ export * from './FiveSDK.js';
8
+ export * from './types.js';
9
+ // export * from './validation/index.js'; // Might rely on broken things
10
+ export * from './lib/bytecode-encoder.js';
11
+ export * from './encoding/ParameterEncoder.js'; // Added missing export
12
+ export * from './crypto/index.js'; // Added missing export (for PDAUtils)
13
+ export * from './project/toml.js';
14
+ export * from './project/config.js';
15
+ export * from './project/workspace.js';
16
+ export * from './wasm/vm.js';
17
+ export * from './wasm/compiler/index.js';
18
+ export * from './wasm/loader.js';
19
+ export * from './testing/index.js';
20
+ // ==================== FiveProgram High-Level API ====================
21
+ export * from './program/index.js';
22
+ export * from './modules/namespaces.js';
23
+ // ==================== Program ID Resolution ====================
24
+ export { ProgramIdResolver, FIVE_BAKED_PROGRAM_ID } from './config/ProgramIdResolver.js';
25
+ // ==================== Constants ====================
26
+ export { FIVE_VM_PROGRAM_ID } from './types.js';
27
+ // Default export disabled for minimal build
28
+ // export { FiveSDK as default };
@@ -0,0 +1,62 @@
1
+ export interface ParameterDefinition {
2
+ name: string;
3
+ type: string;
4
+ isAccount?: boolean;
5
+ is_account?: boolean;
6
+ param_type?: string;
7
+ maxLen?: number;
8
+ }
9
+ export interface ParameterValue {
10
+ [key: string]: any;
11
+ }
12
+ export declare class BytecodeEncoder {
13
+ /**
14
+ * Parse a raw ABI type string into a canonical execute-encoding type.
15
+ * Supports sized string syntax like string<32>.
16
+ */
17
+ static parseTypeSpec(rawType: string): {
18
+ baseType: string;
19
+ maxLen?: number;
20
+ };
21
+ /**
22
+ * Get type ID for encoding.
23
+ */
24
+ static getTypeId(type: string): number;
25
+ /**
26
+ * Encode a 32-bit unsigned integer (Little Endian).
27
+ */
28
+ static encodeU32(value: number): Uint8Array;
29
+ /**
30
+ * Encode execute instruction data using WASM ParameterEncoder.
31
+ */
32
+ static encodeExecute(functionIndex: number, parameters?: ParameterDefinition[], values?: ParameterValue, retry?: boolean, options?: any): Promise<Buffer>;
33
+ private static isAccountParam;
34
+ private static getCanonicalTypeSpec;
35
+ private static normalizeType;
36
+ /**
37
+ * Parse parameter definitions from JSON string
38
+ */
39
+ static parseParameters(parametersJson: string): {
40
+ definitions: ParameterDefinition[];
41
+ values: ParameterValue;
42
+ };
43
+ /**
44
+ * Validate WASM module availability
45
+ */
46
+ static validateWasmModule(): Promise<{
47
+ available: boolean;
48
+ error?: string;
49
+ }>;
50
+ /**
51
+ * Create typed parameter definitions with validation
52
+ */
53
+ static createTypedParameters(params: Array<{
54
+ name: string;
55
+ type: string;
56
+ value: any;
57
+ optional?: boolean;
58
+ }>): {
59
+ definitions: ParameterDefinition[];
60
+ values: ParameterValue;
61
+ };
62
+ }
@@ -0,0 +1,281 @@
1
+ // Bytecode encoder for the Five VM protocol.
2
+ import { getWasmModule } from '../wasm/loader.js';
3
+ let wasmModule = null;
4
+ // Type mapping for encoding - matches Five protocol types.
5
+ const TYPE_IDS = {
6
+ 'u8': 1,
7
+ 'u16': 2,
8
+ 'u32': 3,
9
+ 'u64': 4,
10
+ 'i8': 5,
11
+ 'i16': 6,
12
+ 'i32': 7,
13
+ 'i64': 8,
14
+ 'bool': 9,
15
+ 'pubkey': 10,
16
+ 'string': 11,
17
+ 'account': 12,
18
+ 'bytes': 11,
19
+ 'array': 13
20
+ };
21
+ export class BytecodeEncoder {
22
+ /**
23
+ * Parse a raw ABI type string into a canonical execute-encoding type.
24
+ * Supports sized string syntax like string<32>.
25
+ */
26
+ static parseTypeSpec(rawType) {
27
+ const normalized = (rawType || '').toString().trim().toLowerCase();
28
+ const sizedStringMatch = normalized.match(/^string\s*<\s*(\d+)\s*>$/);
29
+ if (sizedStringMatch) {
30
+ return {
31
+ baseType: 'string',
32
+ maxLen: Number.parseInt(sizedStringMatch[1], 10),
33
+ };
34
+ }
35
+ return { baseType: normalized };
36
+ }
37
+ /**
38
+ * Get type ID for encoding.
39
+ */
40
+ static getTypeId(type) {
41
+ const typeId = TYPE_IDS[type.toLowerCase()];
42
+ if (typeId === undefined) {
43
+ throw new Error(`Unknown type for encoding: ${type}`);
44
+ }
45
+ return typeId;
46
+ }
47
+ /**
48
+ * Encode a 32-bit unsigned integer (Little Endian).
49
+ */
50
+ static encodeU32(value) {
51
+ const buffer = new Uint8Array(4);
52
+ buffer[0] = value & 0xff;
53
+ buffer[1] = (value >> 8) & 0xff;
54
+ buffer[2] = (value >> 16) & 0xff;
55
+ buffer[3] = (value >>> 24) & 0xff;
56
+ return buffer;
57
+ }
58
+ /**
59
+ * Encode execute instruction data using WASM ParameterEncoder.
60
+ */
61
+ static async encodeExecute(functionIndex, parameters = [], values = {}, retry = true, options = {}) {
62
+ // Normalize parameter types before encoding to handle custom types (Mint, TokenAccount, etc.).
63
+ const normalizedParameters = parameters.map(p => {
64
+ const typeSpec = this.getCanonicalTypeSpec(p);
65
+ return {
66
+ ...p,
67
+ type: typeSpec.baseType,
68
+ maxLen: typeSpec.maxLen,
69
+ };
70
+ });
71
+ // Load WASM module using shared loader
72
+ if (!wasmModule) {
73
+ try {
74
+ wasmModule = await getWasmModule();
75
+ // Check if loaded module is valid.
76
+ if (wasmModule && wasmModule.ParameterEncoder) {
77
+ try {
78
+ // Health check: try to encode empty params.
79
+ wasmModule.ParameterEncoder.encode_execute(0, []);
80
+ }
81
+ catch (e) {
82
+ console.warn("[BytecodeEncoder] Module validation failed, falling back:", e.message);
83
+ wasmModule = null; // Force retry with inline loader
84
+ }
85
+ }
86
+ else {
87
+ wasmModule = null;
88
+ }
89
+ }
90
+ catch (e) {
91
+ // Silently ignore loader errors and try fallback
92
+ wasmModule = null;
93
+ }
94
+ // Fallback: import the wasm-pack generated module for Node.js.
95
+ if (!wasmModule && typeof process !== 'undefined') {
96
+ console.log("[DEBUG] (SRC) Attempting wasm-pack module import...");
97
+ try {
98
+ const fs = await import('fs');
99
+ const path = await import('path');
100
+ const url = await import('url');
101
+ const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
102
+ // Import the wasm-pack generated entry point (five_vm_wasm.js)
103
+ // which already handles all the WASM initialization.
104
+ const moduleEntryPath = path.resolve(__dirname, '../assets/vm/five_vm_wasm.js');
105
+ if (fs.existsSync(moduleEntryPath)) {
106
+ console.log("[DEBUG] Found WASM module at:", moduleEntryPath);
107
+ const wasmMod = await import(moduleEntryPath);
108
+ // The wasm-pack module exports the initialized module directly.
109
+ if (wasmMod && wasmMod.ParameterEncoder) {
110
+ wasmModule = wasmMod;
111
+ console.log("[DEBUG] WASM module imported and initialized successfully!");
112
+ }
113
+ else {
114
+ console.error("[DEBUG] WASM module missing expected exports");
115
+ }
116
+ }
117
+ else {
118
+ console.error("[DEBUG] WASM module not found at:", moduleEntryPath);
119
+ }
120
+ }
121
+ catch (err) {
122
+ console.error("[DEBUG] Module import FAILED:", err);
123
+ // Don't throw - let it fall through to error handling below.
124
+ }
125
+ }
126
+ }
127
+ const filteredParams = normalizedParameters;
128
+ const paramValues = filteredParams.map(param => {
129
+ const value = values[param.name];
130
+ if (value === undefined || value === null) {
131
+ throw new Error(`Missing value for parameter: ${param.name}`);
132
+ }
133
+ return { param, value };
134
+ });
135
+ if (options && options.debug) {
136
+ console.log(`[BytecodeEncoder] Parameters:`, paramValues.map(p => ({
137
+ name: p.param.name,
138
+ type: p.param.type || p.param.param_type,
139
+ normalized: this.getCanonicalTypeSpec(p.param).baseType,
140
+ maxLen: this.getCanonicalTypeSpec(p.param).maxLen,
141
+ isAccount: this.isAccountParam(p.param)
142
+ })));
143
+ }
144
+ // Build parameter array with full metadata for fixed-size WASM encoder
145
+ const paramArray = paramValues.map(({ param, value }) => {
146
+ const canonicalType = this.getCanonicalTypeSpec(param);
147
+ // Pass full parameter definition for type-aware encoding
148
+ return {
149
+ name: param.name,
150
+ type: canonicalType.baseType,
151
+ param_type: canonicalType.baseType,
152
+ maxLen: canonicalType.maxLen,
153
+ isAccount: canonicalType.baseType === 'account',
154
+ is_account: canonicalType.baseType === 'account',
155
+ value: value
156
+ };
157
+ });
158
+ try {
159
+ // Debug logging to understand parameter encoding
160
+ console.log(`[BytecodeEncoder] About to encode with paramArray:`, JSON.stringify(paramArray.map(p => ({
161
+ name: p.name || 'unknown',
162
+ type: p.type || 'unknown',
163
+ hasValue: p.value !== undefined
164
+ }))));
165
+ const encoded = wasmModule.ParameterEncoder.encode_execute(functionIndex, paramArray);
166
+ if (options && options.debug) {
167
+ const buf = Buffer.from(encoded);
168
+ console.log(`[BytecodeEncoder] WASM encoded ${paramArray.length} parameters: ${buf.length} bytes`);
169
+ }
170
+ console.log(`[BytecodeEncoder] Encoded result: ${Buffer.from(encoded).toString('hex')}`);
171
+ return Buffer.from(encoded);
172
+ }
173
+ catch (e) {
174
+ console.warn("[BytecodeEncoder] Encode failed via WASM:", e);
175
+ if (retry) {
176
+ console.warn("[BytecodeEncoder] Reloading WASM module and retrying...");
177
+ wasmModule = null; // Force reload.
178
+ return this.encodeExecute(functionIndex, parameters, values, false, options);
179
+ }
180
+ throw e;
181
+ }
182
+ }
183
+ static isAccountParam(param) {
184
+ if (param.isAccount || param.is_account) {
185
+ return true;
186
+ }
187
+ const type = this.getCanonicalTypeSpec(param).baseType;
188
+ return type === 'account';
189
+ }
190
+ static getCanonicalTypeSpec(param) {
191
+ if (param.isAccount || param.is_account) {
192
+ return { baseType: 'account' };
193
+ }
194
+ const rawType = (param.type || param.param_type || '').toString().trim();
195
+ const parsed = this.parseTypeSpec(rawType);
196
+ const explicitMaxLen = param.maxLen;
197
+ if (parsed.baseType === 'string' &&
198
+ explicitMaxLen !== undefined &&
199
+ explicitMaxLen !== null) {
200
+ const maxLen = Number.parseInt(String(explicitMaxLen), 10);
201
+ if (!Number.isNaN(maxLen)) {
202
+ return { baseType: 'string', maxLen };
203
+ }
204
+ }
205
+ // Special handling for common account-backed types in the DSL
206
+ if (['mint', 'tokenaccount'].includes(parsed.baseType)) {
207
+ return { baseType: 'account' };
208
+ }
209
+ return parsed;
210
+ }
211
+ static normalizeType(param) {
212
+ return this.getCanonicalTypeSpec(param).baseType;
213
+ }
214
+ /**
215
+ * Parse parameter definitions from JSON string
216
+ */
217
+ static parseParameters(parametersJson) {
218
+ try {
219
+ const parsed = JSON.parse(parametersJson);
220
+ if (Array.isArray(parsed)) {
221
+ // Array format: [{ name: "a", type: "u64", value: 123 }, ...]
222
+ const definitions = [];
223
+ const values = {};
224
+ for (const param of parsed) {
225
+ if (!param.name || !param.type || param.value === undefined) {
226
+ throw new Error('Parameter must have name, type, and value fields');
227
+ }
228
+ definitions.push({ name: param.name, type: param.type });
229
+ values[param.name] = param.value;
230
+ }
231
+ return { definitions, values };
232
+ }
233
+ else {
234
+ throw new Error('Object format parameters require type definitions. Use array format: [{ name: "a", type: "u64", value: 123 }]');
235
+ }
236
+ }
237
+ catch (error) {
238
+ throw new Error(`Invalid parameters JSON: ${error instanceof Error ? error.message : 'Unknown error'}`);
239
+ }
240
+ }
241
+ /**
242
+ * Validate WASM module availability
243
+ */
244
+ static async validateWasmModule() {
245
+ try {
246
+ if (!wasmModule) {
247
+ wasmModule = await getWasmModule();
248
+ }
249
+ if (!wasmModule.ParameterEncoder) {
250
+ return { available: false, error: 'ParameterEncoder not found in WASM module' };
251
+ }
252
+ return { available: true };
253
+ }
254
+ catch (error) {
255
+ return {
256
+ available: false,
257
+ error: `WASM module not available: ${error instanceof Error ? error.message : 'Unknown error'}`
258
+ };
259
+ }
260
+ }
261
+ /**
262
+ * Create typed parameter definitions with validation
263
+ */
264
+ static createTypedParameters(params) {
265
+ const definitions = [];
266
+ const values = {};
267
+ for (const param of params) {
268
+ if (!TYPE_IDS[param.type.toLowerCase()]) {
269
+ throw new Error(`Unknown parameter type: ${param.type}`);
270
+ }
271
+ if (!param.optional && (param.value === undefined || param.value === null)) {
272
+ throw new Error(`Missing value for required parameter: ${param.name}`);
273
+ }
274
+ definitions.push({ name: param.name, type: param.type });
275
+ if (param.value !== undefined) {
276
+ values[param.name] = param.value;
277
+ }
278
+ }
279
+ return { definitions, values };
280
+ }
281
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Simple logging that can be silenced in production
3
+ */
4
+ export declare const log: {
5
+ debug: (message: string, ...args: any[]) => void;
6
+ info: (message: string, ...args: any[]) => void;
7
+ warn: (message: string, ...args: any[]) => void;
8
+ error: (message: string, ...args: any[]) => void;
9
+ };