@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.
- package/README.md +16 -0
- package/dist/FiveSDK.d.ts +45 -1
- package/dist/FiveSDK.js +6 -0
- package/dist/accounts/index.d.ts +10 -28
- package/dist/accounts/index.js +33 -61
- package/dist/assets/vm/five_vm_wasm.d.ts +8 -0
- package/dist/assets/vm/five_vm_wasm.js +25 -0
- package/dist/assets/vm/five_vm_wasm_bg.wasm +0 -0
- package/dist/assets/vm/five_vm_wasm_bg.wasm.d.ts +3 -0
- package/dist/compiler/BytecodeCompiler.js +10 -6
- package/dist/compiler/source-normalization.d.ts +1 -0
- package/dist/compiler/source-normalization.js +67 -0
- package/dist/constants/headers.d.ts +2 -0
- package/dist/constants/headers.js +2 -0
- package/dist/crypto/index.d.ts +8 -1
- package/dist/crypto/index.js +27 -14
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/modules/accounts.js +1 -1
- package/dist/modules/deploy.js +172 -99
- package/dist/modules/execute.d.ts +5 -0
- package/dist/modules/execute.js +115 -49
- package/dist/modules/fees.js +2 -2
- package/dist/modules/namespaces.d.ts +11 -0
- package/dist/modules/namespaces.js +64 -0
- package/dist/program/FiveProgram.js +4 -3
- package/dist/program/FunctionBuilder.d.ts +8 -0
- package/dist/program/FunctionBuilder.js +18 -5
- package/dist/program/TypeGenerator.js +8 -1
- package/dist/project/config.js +113 -1
- package/dist/project/workspace.d.ts +5 -0
- package/dist/testing/TestDiscovery.d.ts +1 -0
- package/dist/testing/TestDiscovery.js +18 -2
- package/dist/testing/TestRunner.js +4 -1
- package/dist/types.d.ts +16 -5
- package/dist/types.js +1 -0
- package/dist/utils/abi.js +33 -10
- package/dist/utils/transaction.d.ts +16 -0
- package/dist/utils/transaction.js +81 -5
- package/dist/wasm/compiler/CompilationLogic.js +3 -3
- package/dist/wasm/vm.d.ts +2 -2
- package/dist/wasm/vm.js +10 -11
- package/package.json +1 -1
- package/dist/assets/vm/dummy.file +0 -0
- package/dist/assets/vm/five_vm_wasm_bg.js +0 -3307
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './wasm/vm.js';
|
|
|
15
15
|
export * from './wasm/compiler/index.js';
|
|
16
16
|
export * from './wasm/loader.js';
|
|
17
17
|
export * from './testing/index.js';
|
|
18
|
+
export * from './utils/abi.js';
|
|
18
19
|
export * from './program/index.js';
|
|
19
20
|
export * from './modules/namespaces.js';
|
|
20
21
|
export { ProgramIdResolver } from './config/ProgramIdResolver.js';
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export * from './wasm/vm.js';
|
|
|
17
17
|
export * from './wasm/compiler/index.js';
|
|
18
18
|
export * from './wasm/loader.js';
|
|
19
19
|
export * from './testing/index.js';
|
|
20
|
+
export * from './utils/abi.js';
|
|
20
21
|
// ==================== FiveProgram High-Level API ====================
|
|
21
22
|
export * from './program/index.js';
|
|
22
23
|
export * from './modules/namespaces.js';
|
package/dist/modules/accounts.js
CHANGED
|
@@ -255,7 +255,7 @@ export async function validateBytecodeEncoding(bytecode, debug = false) {
|
|
|
255
255
|
error: 'Invalid Five VM magic bytes (expected "5IVE")',
|
|
256
256
|
};
|
|
257
257
|
}
|
|
258
|
-
//
|
|
258
|
+
// ScriptBytecodeHeaderV1:
|
|
259
259
|
// 0-3: Magic
|
|
260
260
|
// 4-7: Features (u32 LE)
|
|
261
261
|
// 8: Public Function Count (u8)
|
package/dist/modules/deploy.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { PDAUtils, RentCalculator } from "../crypto/index.js";
|
|
2
2
|
import { validator, Validators } from "../validation/index.js";
|
|
3
3
|
import { calculateDeployFee } from "./fees.js";
|
|
4
|
-
import {
|
|
4
|
+
import { getAccountInfoWithRetry, sendAndConfirmRawTransactionRobust, SDK_COMMITMENTS, } from "../utils/transaction.js";
|
|
5
5
|
import { ProgramIdResolver } from "../config/ProgramIdResolver.js";
|
|
6
6
|
import { VmClusterConfigResolver } from "../config/VmClusterConfigResolver.js";
|
|
7
|
+
import { SCRIPT_ACCOUNT_HEADER_LEN } from "../constants/headers.js";
|
|
7
8
|
const DEFAULT_FEE_VAULT_SHARD_COUNT = (() => {
|
|
8
9
|
try {
|
|
9
10
|
return VmClusterConfigResolver.loadClusterConfig().feeVaultShardCount;
|
|
@@ -16,6 +17,24 @@ const FEE_VAULT_NAMESPACE_SEED = Buffer.from([
|
|
|
16
17
|
0xff, 0x66, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x6d, 0x5f, 0x66, 0x65, 0x65,
|
|
17
18
|
0x5f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x31,
|
|
18
19
|
]);
|
|
20
|
+
function clampShardCount(rawCount) {
|
|
21
|
+
const normalized = rawCount > 0 ? rawCount : DEFAULT_FEE_VAULT_SHARD_COUNT;
|
|
22
|
+
return Math.max(1, Math.min(DEFAULT_FEE_VAULT_SHARD_COUNT, normalized));
|
|
23
|
+
}
|
|
24
|
+
function normalizeRpcEndpoint(connection) {
|
|
25
|
+
return String(connection?.rpcEndpoint || connection?._rpcEndpoint || "").toLowerCase();
|
|
26
|
+
}
|
|
27
|
+
function isLocalnetBootstrapConnection(connection, network) {
|
|
28
|
+
const normalizedNetwork = String(network || "").toLowerCase();
|
|
29
|
+
if (normalizedNetwork === "localnet") {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
const endpoint = normalizeRpcEndpoint(connection);
|
|
33
|
+
return endpoint.includes("127.0.0.1") || endpoint.includes("localhost");
|
|
34
|
+
}
|
|
35
|
+
function selectBootstrapCommitment(connection, network) {
|
|
36
|
+
return isLocalnetBootstrapConnection(connection, network) ? "confirmed" : "finalized";
|
|
37
|
+
}
|
|
19
38
|
async function readVMStateFeeConfig(connection, vmStateAddress) {
|
|
20
39
|
if (!connection) {
|
|
21
40
|
return { shardCount: DEFAULT_FEE_VAULT_SHARD_COUNT };
|
|
@@ -37,7 +56,7 @@ async function readVMStateFeeConfig(connection, vmStateAddress) {
|
|
|
37
56
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
38
57
|
const deployFeeLamports = view.getUint32(40, true);
|
|
39
58
|
const shardCountRaw = data.length > 50 ? data[50] : 0;
|
|
40
|
-
const shardCount = shardCountRaw
|
|
59
|
+
const shardCount = clampShardCount(shardCountRaw);
|
|
41
60
|
return { deployFeeLamports, shardCount };
|
|
42
61
|
}
|
|
43
62
|
catch {
|
|
@@ -49,16 +68,50 @@ async function deriveProgramFeeVault(programId, shardIndex) {
|
|
|
49
68
|
const [pda, bump] = PublicKey.findProgramAddressSync([FEE_VAULT_NAMESPACE_SEED, Buffer.from([shardIndex])], new PublicKey(programId));
|
|
50
69
|
return { address: pda.toBase58(), bump };
|
|
51
70
|
}
|
|
71
|
+
async function resolveScriptAccountDerivation(bytecode, deployer, programId, options) {
|
|
72
|
+
const { PublicKey } = await import("@solana/web3.js");
|
|
73
|
+
if (options.scriptAccount) {
|
|
74
|
+
validator.validateBase58Address(options.scriptAccount, "options.scriptAccount");
|
|
75
|
+
if (!options.scriptSeed) {
|
|
76
|
+
throw new Error("options.scriptSeed is required when options.scriptAccount is provided");
|
|
77
|
+
}
|
|
78
|
+
const expectedAccount = await PublicKey.createWithSeed(new PublicKey(deployer), options.scriptSeed, new PublicKey(programId));
|
|
79
|
+
if (expectedAccount.toBase58() !== options.scriptAccount) {
|
|
80
|
+
throw new Error("options.scriptAccount does not match the derived address for the provided deployer, scriptSeed, and programId");
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
address: options.scriptAccount,
|
|
84
|
+
bump: 0,
|
|
85
|
+
seed: options.scriptSeed,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return PDAUtils.deriveScriptAccount(bytecode, deployer, programId);
|
|
89
|
+
}
|
|
52
90
|
function createInitFeeVaultInstructionData(shardIndex, bump) {
|
|
53
91
|
return Uint8Array.from([11, shardIndex & 0xff, bump & 0xff]);
|
|
54
92
|
}
|
|
55
93
|
async function initProgramFeeVaultShards(connection, programId, vmStateAccount, shardCount, payer, options = {}) {
|
|
56
94
|
const { PublicKey, Transaction, TransactionInstruction, SystemProgram } = await import("@solana/web3.js");
|
|
57
95
|
const signatures = [];
|
|
58
|
-
|
|
96
|
+
const effectiveShardCount = clampShardCount(shardCount);
|
|
97
|
+
const programPubkey = new PublicKey(programId);
|
|
98
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection);
|
|
99
|
+
for (let shardIndex = 0; shardIndex < effectiveShardCount; shardIndex++) {
|
|
59
100
|
const vault = await deriveProgramFeeVault(programId, shardIndex);
|
|
101
|
+
const existingVault = await getAccountInfoWithRetry(connection, new PublicKey(vault.address), {
|
|
102
|
+
commitment: bootstrapCommitment,
|
|
103
|
+
retries: 1,
|
|
104
|
+
delayMs: 500,
|
|
105
|
+
debug: options.debug,
|
|
106
|
+
});
|
|
107
|
+
if (existingVault?.owner && new PublicKey(existingVault.owner).equals(programPubkey)) {
|
|
108
|
+
if (options.debug) {
|
|
109
|
+
console.log(`[FiveSDK] Fee vault shard ${shardIndex} already initialized: ${vault.address}`);
|
|
110
|
+
}
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
60
113
|
const tx = new Transaction().add(new TransactionInstruction({
|
|
61
|
-
programId:
|
|
114
|
+
programId: programPubkey,
|
|
62
115
|
keys: [
|
|
63
116
|
{ pubkey: new PublicKey(vmStateAccount), isSigner: false, isWritable: false },
|
|
64
117
|
{ pubkey: payer.publicKey, isSigner: true, isWritable: true },
|
|
@@ -67,24 +120,24 @@ async function initProgramFeeVaultShards(connection, programId, vmStateAccount,
|
|
|
67
120
|
],
|
|
68
121
|
data: Buffer.from(createInitFeeVaultInstructionData(shardIndex, vault.bump)),
|
|
69
122
|
}));
|
|
70
|
-
const
|
|
71
|
-
tx.recentBlockhash = blockhash;
|
|
123
|
+
const latestBlockhash = await connection.getLatestBlockhash("confirmed");
|
|
124
|
+
tx.recentBlockhash = latestBlockhash.blockhash;
|
|
72
125
|
tx.feePayer = payer.publicKey;
|
|
73
126
|
tx.partialSign(payer);
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
preflightCommitment: "confirmed",
|
|
77
|
-
maxRetries: options.maxRetries || 3,
|
|
78
|
-
});
|
|
79
|
-
const shardConfirm = await confirmTransactionRobust(connection, sig, {
|
|
80
|
-
commitment: "finalized",
|
|
127
|
+
const shardSend = await sendAndConfirmRawTransactionRobust(connection, tx.serialize(), {
|
|
128
|
+
commitment: bootstrapCommitment,
|
|
81
129
|
timeoutMs: 120000,
|
|
82
130
|
debug: options.debug,
|
|
131
|
+
maxRetries: options.maxRetries || 3,
|
|
132
|
+
skipPreflight: false,
|
|
133
|
+
preflightCommitment: "confirmed",
|
|
134
|
+
blockhash: latestBlockhash.blockhash,
|
|
135
|
+
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
|
|
83
136
|
});
|
|
84
|
-
if (!
|
|
85
|
-
throw new Error(`Fee vault shard init failed: ${
|
|
137
|
+
if (!shardSend.success || !shardSend.signature) {
|
|
138
|
+
throw new Error(`Fee vault shard init failed: ${shardSend.error || "unconfirmed"}`);
|
|
86
139
|
}
|
|
87
|
-
signatures.push(
|
|
140
|
+
signatures.push(shardSend.signature);
|
|
88
141
|
if (options.debug) {
|
|
89
142
|
console.log(`[FiveSDK] Initialized fee vault shard ${shardIndex}: ${vault.address}`);
|
|
90
143
|
}
|
|
@@ -95,9 +148,6 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
|
|
|
95
148
|
Validators.bytecode(bytecode);
|
|
96
149
|
validator.validateBase58Address(deployer, "deployer");
|
|
97
150
|
Validators.options(options);
|
|
98
|
-
if (options.scriptAccount) {
|
|
99
|
-
validator.validateBase58Address(options.scriptAccount, "options.scriptAccount");
|
|
100
|
-
}
|
|
101
151
|
// Resolve program ID with consistent precedence
|
|
102
152
|
const programId = ProgramIdResolver.resolve(fiveVMProgramId || options.fiveVMProgramId);
|
|
103
153
|
const exportMetadata = encodeExportMetadata(options.exportMetadata);
|
|
@@ -105,7 +155,7 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
|
|
|
105
155
|
console.log(`[FiveSDK] Generating deployment transaction (${bytecode.length} bytes)...`);
|
|
106
156
|
console.log(`[FiveSDK] Using program ID: ${programId}`);
|
|
107
157
|
}
|
|
108
|
-
const scriptResult = await
|
|
158
|
+
const scriptResult = await resolveScriptAccountDerivation(bytecode, deployer, programId, options);
|
|
109
159
|
const scriptAccount = scriptResult.address;
|
|
110
160
|
const scriptSeed = scriptResult.seed;
|
|
111
161
|
const vmStatePDAResult = await PDAUtils.deriveVMStatePDA(programId);
|
|
@@ -114,9 +164,8 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
|
|
|
114
164
|
console.log(`[FiveSDK] Script Account: ${scriptAccount} (seed: ${scriptSeed})`);
|
|
115
165
|
console.log(`[FiveSDK] VM State PDA: ${vmStatePDA}`);
|
|
116
166
|
}
|
|
117
|
-
const
|
|
118
|
-
const
|
|
119
|
-
const rentLamports = await RentCalculator.calculateRentExemption(totalAccountSize);
|
|
167
|
+
const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
|
|
168
|
+
const rentLamports = await RentCalculator.calculateRentExemptionWithConnection(totalAccountSize, connection);
|
|
120
169
|
const { deployFeeLamports } = await readVMStateFeeConfig(connection, vmStatePDA);
|
|
121
170
|
const deployShardIndex = 0;
|
|
122
171
|
const deployVault = await deriveProgramFeeVault(programId, deployShardIndex);
|
|
@@ -191,9 +240,8 @@ options = {}) {
|
|
|
191
240
|
const scriptKeypair = Keypair.generate();
|
|
192
241
|
const scriptAccount = scriptKeypair.publicKey.toString();
|
|
193
242
|
// Calculate account size and rent
|
|
194
|
-
const SCRIPT_HEADER_SIZE = 64; // ScriptHeader::LEN
|
|
195
243
|
const exportMetadata = encodeExportMetadata(options.exportMetadata);
|
|
196
|
-
const totalAccountSize =
|
|
244
|
+
const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
|
|
197
245
|
const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
|
|
198
246
|
const vmStatePDA = await PDAUtils.deriveVMStatePDA(programIdStr);
|
|
199
247
|
const vmStatePubkey = new PublicKey(vmStatePDA.address);
|
|
@@ -211,7 +259,8 @@ options = {}) {
|
|
|
211
259
|
}));
|
|
212
260
|
}
|
|
213
261
|
// 1. Initialize canonical VM State if missing
|
|
214
|
-
const
|
|
262
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection);
|
|
263
|
+
const vmStateInfo = await connection.getAccountInfo(vmStatePubkey, bootstrapCommitment);
|
|
215
264
|
if (!vmStateInfo) {
|
|
216
265
|
tx.add(new TransactionInstruction({
|
|
217
266
|
keys: [
|
|
@@ -275,17 +324,18 @@ options = {}) {
|
|
|
275
324
|
console.log(`[FiveSDK] Generated script keypair: ${scriptAccount}`);
|
|
276
325
|
}
|
|
277
326
|
// Calculate account size and rent
|
|
278
|
-
const SCRIPT_HEADER_SIZE = 64; // ScriptHeader::LEN (five-protocol)
|
|
279
327
|
const exportMetadata = encodeExportMetadata(options.exportMetadata);
|
|
280
|
-
const totalAccountSize =
|
|
328
|
+
const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
|
|
281
329
|
const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
|
|
282
330
|
const vmStateResolution = await ensureCanonicalVmStateAccount(connection, deployerKeypair, new PublicKey(programId), {
|
|
283
331
|
vmStateAccount: options.vmStateAccount,
|
|
284
332
|
maxRetries: options.maxRetries,
|
|
285
333
|
debug: options.debug,
|
|
334
|
+
network: options.network,
|
|
286
335
|
});
|
|
287
336
|
const vmStatePubkey = vmStateResolution.vmStatePubkey;
|
|
288
337
|
const vmStateRent = vmStateResolution.vmStateRent;
|
|
338
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
|
|
289
339
|
const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
|
|
290
340
|
const deployShardIndex = 0;
|
|
291
341
|
const deployVault = await deriveProgramFeeVault(programId, deployShardIndex);
|
|
@@ -308,7 +358,7 @@ options = {}) {
|
|
|
308
358
|
console.log(`[FiveSDK] Export metadata size: ${exportMetadata.length} bytes`);
|
|
309
359
|
console.log(`[FiveSDK] Rent cost: ${((rentLamports + vmStateRent) / 1e9)} SOL`);
|
|
310
360
|
}
|
|
311
|
-
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programId, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries });
|
|
361
|
+
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programId, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries, network: options.network });
|
|
312
362
|
// SINGLE TRANSACTION: create script account + deploy bytecode
|
|
313
363
|
const tx = new Transaction();
|
|
314
364
|
// Optional compute budget
|
|
@@ -373,19 +423,20 @@ options = {}) {
|
|
|
373
423
|
if (options.debug) {
|
|
374
424
|
console.log(`[FiveSDK] Transaction serialized: ${txSerialized.length} bytes`);
|
|
375
425
|
}
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
|
|
426
|
+
const sendResult = await sendAndConfirmRawTransactionRobust(connection, txSerialized, {
|
|
427
|
+
commitment: "confirmed",
|
|
428
|
+
timeoutMs: 120000,
|
|
429
|
+
debug: options.debug,
|
|
379
430
|
maxRetries: options.maxRetries || 3,
|
|
431
|
+
skipPreflight: false,
|
|
432
|
+
preflightCommitment: "confirmed",
|
|
380
433
|
});
|
|
434
|
+
const signature = sendResult.signature;
|
|
381
435
|
if (options.debug) {
|
|
382
436
|
console.log(`[FiveSDK] sendRawTransaction completed, returned signature: ${signature}`);
|
|
383
437
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
options.debug);
|
|
387
|
-
if (!confirmationResult.success) {
|
|
388
|
-
const errorMessage = `Deployment confirmation failed: ${confirmationResult.error || "Unknown error"}`;
|
|
438
|
+
if (!sendResult.success || !signature) {
|
|
439
|
+
const errorMessage = `Deployment confirmation failed: ${sendResult.error || "Unknown error"}`;
|
|
389
440
|
if (options.debug)
|
|
390
441
|
console.log(`[FiveSDK] ${errorMessage}`);
|
|
391
442
|
return {
|
|
@@ -394,8 +445,8 @@ options = {}) {
|
|
|
394
445
|
transactionId: signature,
|
|
395
446
|
};
|
|
396
447
|
}
|
|
397
|
-
if (
|
|
398
|
-
const errorMessage = `Combined deployment failed: ${JSON.stringify(
|
|
448
|
+
if (sendResult.err) {
|
|
449
|
+
const errorMessage = `Combined deployment failed: ${JSON.stringify(sendResult.err)}`;
|
|
399
450
|
if (options.debug)
|
|
400
451
|
console.log(`[FiveSDK] ${errorMessage}`);
|
|
401
452
|
return {
|
|
@@ -463,8 +514,7 @@ options = {}) {
|
|
|
463
514
|
const scriptKeypair = Keypair.generate();
|
|
464
515
|
const scriptAccount = scriptKeypair.publicKey.toString();
|
|
465
516
|
// Calculate account size and rent
|
|
466
|
-
const
|
|
467
|
-
const totalAccountSize = SCRIPT_HEADER_SIZE + bytecode.length;
|
|
517
|
+
const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
|
|
468
518
|
const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
|
|
469
519
|
const programIdStr = ProgramIdResolver.resolve(options.fiveVMProgramId);
|
|
470
520
|
const programId = new PublicKey(programIdStr);
|
|
@@ -472,9 +522,11 @@ options = {}) {
|
|
|
472
522
|
vmStateAccount: options.vmStateAccount,
|
|
473
523
|
maxRetries: options.maxRetries,
|
|
474
524
|
debug: options.debug,
|
|
525
|
+
network: options.network,
|
|
475
526
|
});
|
|
476
527
|
const vmStatePubkey = vmStateResolution.vmStatePubkey;
|
|
477
528
|
const vmStateRent = vmStateResolution.vmStateRent;
|
|
529
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
|
|
478
530
|
const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
|
|
479
531
|
const deployShardIndex = 0;
|
|
480
532
|
const deployVault = await deriveProgramFeeVault(programIdStr, deployShardIndex);
|
|
@@ -496,7 +548,7 @@ options = {}) {
|
|
|
496
548
|
console.log(`[FiveSDK] Total account size: ${totalAccountSize} bytes`);
|
|
497
549
|
console.log(`[FiveSDK] Initial rent cost: ${(rentLamports + vmStateRent) / 1e9} SOL`);
|
|
498
550
|
}
|
|
499
|
-
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries });
|
|
551
|
+
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries, network: options.network });
|
|
500
552
|
const transactionIds = [];
|
|
501
553
|
let totalCost = rentLamports + vmStateRent;
|
|
502
554
|
// TRANSACTION 1: Create Account + InitLargeProgram
|
|
@@ -509,7 +561,7 @@ options = {}) {
|
|
|
509
561
|
fromPubkey: deployerKeypair.publicKey,
|
|
510
562
|
newAccountPubkey: scriptKeypair.publicKey,
|
|
511
563
|
lamports: rentLamports,
|
|
512
|
-
space:
|
|
564
|
+
space: SCRIPT_ACCOUNT_HEADER_LEN, // Start with just the ScriptAccountHeader
|
|
513
565
|
programId: programId,
|
|
514
566
|
});
|
|
515
567
|
initTransaction.add(createAccountInstruction);
|
|
@@ -530,7 +582,7 @@ options = {}) {
|
|
|
530
582
|
{
|
|
531
583
|
pubkey: vmStatePubkey,
|
|
532
584
|
isSigner: false,
|
|
533
|
-
isWritable:
|
|
585
|
+
isWritable: true,
|
|
534
586
|
},
|
|
535
587
|
...feeVaultKeys,
|
|
536
588
|
],
|
|
@@ -540,23 +592,24 @@ options = {}) {
|
|
|
540
592
|
initTransaction.add(initLargeProgramInstruction);
|
|
541
593
|
// Sign and send initialization transaction
|
|
542
594
|
initTransaction.feePayer = deployerKeypair.publicKey;
|
|
543
|
-
const
|
|
544
|
-
initTransaction.recentBlockhash = blockhash;
|
|
595
|
+
const initBlockhash = await connection.getLatestBlockhash("confirmed");
|
|
596
|
+
initTransaction.recentBlockhash = initBlockhash.blockhash;
|
|
545
597
|
initTransaction.partialSign(deployerKeypair);
|
|
546
598
|
initTransaction.partialSign(scriptKeypair);
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
preflightCommitment: "confirmed",
|
|
550
|
-
maxRetries: options.maxRetries || 3,
|
|
551
|
-
});
|
|
552
|
-
const initConfirm = await confirmTransactionRobust(connection, initSignature, {
|
|
553
|
-
commitment: "finalized",
|
|
599
|
+
const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
|
|
600
|
+
commitment: bootstrapCommitment,
|
|
554
601
|
timeoutMs: 120000,
|
|
555
602
|
debug: options.debug,
|
|
603
|
+
maxRetries: options.maxRetries || 3,
|
|
604
|
+
skipPreflight: false,
|
|
605
|
+
preflightCommitment: "confirmed",
|
|
606
|
+
blockhash: initBlockhash.blockhash,
|
|
607
|
+
lastValidBlockHeight: initBlockhash.lastValidBlockHeight,
|
|
556
608
|
});
|
|
557
|
-
if (!
|
|
558
|
-
throw new Error(`Initialization confirmation failed: ${
|
|
609
|
+
if (!initSend.success || !initSend.signature) {
|
|
610
|
+
throw new Error(`Initialization confirmation failed: ${initSend.error || "unconfirmed"}`);
|
|
559
611
|
}
|
|
612
|
+
const initSignature = initSend.signature;
|
|
560
613
|
transactionIds.push(initSignature);
|
|
561
614
|
if (options.debug) {
|
|
562
615
|
console.log(`[FiveSDK] ✅ Initialization completed: ${initSignature}`);
|
|
@@ -575,7 +628,7 @@ options = {}) {
|
|
|
575
628
|
console.log(`[FiveSDK] Step ${i + 2}: Appending chunk ${i + 1}/${chunks.length} (${chunk.length} bytes)`);
|
|
576
629
|
}
|
|
577
630
|
// Calculate additional rent needed for this chunk
|
|
578
|
-
const currentInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, { commitment:
|
|
631
|
+
const currentInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, { commitment: bootstrapCommitment, retries: 2, delayMs: 1000, debug: options.debug });
|
|
579
632
|
if (!currentInfo)
|
|
580
633
|
throw new Error("Script account not found after initialization");
|
|
581
634
|
const newSize = currentInfo.data.length + chunk.length;
|
|
@@ -628,7 +681,7 @@ options = {}) {
|
|
|
628
681
|
{
|
|
629
682
|
pubkey: vmStatePubkey,
|
|
630
683
|
isSigner: false,
|
|
631
|
-
isWritable:
|
|
684
|
+
isWritable: true,
|
|
632
685
|
},
|
|
633
686
|
...feeVaultKeys,
|
|
634
687
|
],
|
|
@@ -641,19 +694,20 @@ options = {}) {
|
|
|
641
694
|
appendTransaction.feePayer = deployerKeypair.publicKey;
|
|
642
695
|
appendTransaction.recentBlockhash = appendBlockhash.blockhash;
|
|
643
696
|
appendTransaction.partialSign(deployerKeypair);
|
|
644
|
-
const
|
|
645
|
-
|
|
646
|
-
preflightCommitment: "confirmed",
|
|
647
|
-
maxRetries: options.maxRetries || 3,
|
|
648
|
-
});
|
|
649
|
-
const appendConfirm = await confirmTransactionRobust(connection, appendSignature, {
|
|
650
|
-
commitment: "finalized",
|
|
697
|
+
const appendSend = await sendAndConfirmRawTransactionRobust(connection, appendTransaction.serialize(), {
|
|
698
|
+
commitment: bootstrapCommitment,
|
|
651
699
|
timeoutMs: 120000,
|
|
652
700
|
debug: options.debug,
|
|
701
|
+
maxRetries: options.maxRetries || 3,
|
|
702
|
+
skipPreflight: false,
|
|
703
|
+
preflightCommitment: "confirmed",
|
|
704
|
+
blockhash: appendBlockhash.blockhash,
|
|
705
|
+
lastValidBlockHeight: appendBlockhash.lastValidBlockHeight,
|
|
653
706
|
});
|
|
654
|
-
if (!
|
|
655
|
-
throw new Error(`Append confirmation failed: ${
|
|
707
|
+
if (!appendSend.success || !appendSend.signature) {
|
|
708
|
+
throw new Error(`Append confirmation failed: ${appendSend.error || "unconfirmed"}`);
|
|
656
709
|
}
|
|
710
|
+
const appendSignature = appendSend.signature;
|
|
657
711
|
transactionIds.push(appendSignature);
|
|
658
712
|
if (options.debug) {
|
|
659
713
|
console.log(`[FiveSDK] ✅ Chunk ${i + 1} appended: ${appendSignature}`);
|
|
@@ -661,7 +715,7 @@ options = {}) {
|
|
|
661
715
|
}
|
|
662
716
|
// Final verification
|
|
663
717
|
let finalInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, {
|
|
664
|
-
commitment:
|
|
718
|
+
commitment: bootstrapCommitment,
|
|
665
719
|
retries: 2,
|
|
666
720
|
delayMs: 1000,
|
|
667
721
|
debug: options.debug,
|
|
@@ -669,7 +723,7 @@ options = {}) {
|
|
|
669
723
|
if (!finalInfo) {
|
|
670
724
|
throw new Error("Script account not found during final verification");
|
|
671
725
|
}
|
|
672
|
-
const expectedSize =
|
|
726
|
+
const expectedSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
|
|
673
727
|
if (options.debug) {
|
|
674
728
|
console.log(`[FiveSDK] 🔍 Final verification:`);
|
|
675
729
|
console.log(`[FiveSDK] Expected size: ${expectedSize} bytes`);
|
|
@@ -733,8 +787,7 @@ options = {}) {
|
|
|
733
787
|
const scriptKeypair = Keypair.generate();
|
|
734
788
|
const scriptAccount = scriptKeypair.publicKey.toString();
|
|
735
789
|
// Calculate full account size upfront
|
|
736
|
-
const
|
|
737
|
-
const totalAccountSize = SCRIPT_HEADER_SIZE + bytecode.length;
|
|
790
|
+
const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
|
|
738
791
|
const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
|
|
739
792
|
const programIdStr = ProgramIdResolver.resolve(options.fiveVMProgramId);
|
|
740
793
|
const programId = new PublicKey(programIdStr);
|
|
@@ -742,9 +795,11 @@ options = {}) {
|
|
|
742
795
|
vmStateAccount: options.vmStateAccount,
|
|
743
796
|
maxRetries: options.maxRetries,
|
|
744
797
|
debug: options.debug,
|
|
798
|
+
network: options.network,
|
|
745
799
|
});
|
|
746
800
|
const vmStatePubkey = vmStateResolution.vmStatePubkey;
|
|
747
801
|
const vmStateRent = vmStateResolution.vmStateRent;
|
|
802
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
|
|
748
803
|
const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
|
|
749
804
|
const deployShardIndex = 0;
|
|
750
805
|
const deployVault = await deriveProgramFeeVault(programIdStr, deployShardIndex);
|
|
@@ -766,7 +821,7 @@ options = {}) {
|
|
|
766
821
|
console.log(`[FiveSDK] PRE-ALLOCATED full account size: ${totalAccountSize} bytes`);
|
|
767
822
|
console.log(`[FiveSDK] Full rent cost paid upfront: ${(rentLamports + vmStateRent) / 1e9} SOL`);
|
|
768
823
|
}
|
|
769
|
-
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries });
|
|
824
|
+
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries, network: options.network });
|
|
770
825
|
const transactionIds = [];
|
|
771
826
|
let totalCost = rentLamports + vmStateRent;
|
|
772
827
|
const chunks = chunkBytecode(bytecode, chunkSize);
|
|
@@ -803,7 +858,7 @@ options = {}) {
|
|
|
803
858
|
{
|
|
804
859
|
pubkey: vmStatePubkey,
|
|
805
860
|
isSigner: false,
|
|
806
|
-
isWritable:
|
|
861
|
+
isWritable: true,
|
|
807
862
|
},
|
|
808
863
|
...feeVaultKeys,
|
|
809
864
|
],
|
|
@@ -816,19 +871,24 @@ options = {}) {
|
|
|
816
871
|
initTransaction.recentBlockhash = blockhash;
|
|
817
872
|
initTransaction.partialSign(deployerKeypair);
|
|
818
873
|
initTransaction.partialSign(scriptKeypair);
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
|
|
874
|
+
const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
|
|
875
|
+
commitment: "confirmed",
|
|
876
|
+
timeoutMs: 120000,
|
|
877
|
+
debug: options.debug,
|
|
822
878
|
maxRetries: options.maxRetries || 3,
|
|
879
|
+
skipPreflight: false,
|
|
880
|
+
preflightCommitment: "confirmed",
|
|
881
|
+
blockhash: blockhash,
|
|
882
|
+
lastValidBlockHeight: undefined,
|
|
823
883
|
});
|
|
824
|
-
|
|
825
|
-
if (!initConfirmation.success) {
|
|
884
|
+
if (!initSend.success || !initSend.signature) {
|
|
826
885
|
return {
|
|
827
886
|
success: false,
|
|
828
|
-
error: `Initialization confirmation failed: ${
|
|
887
|
+
error: `Initialization confirmation failed: ${initSend.error}`,
|
|
829
888
|
transactionIds
|
|
830
889
|
};
|
|
831
890
|
}
|
|
891
|
+
const initSignature = initSend.signature;
|
|
832
892
|
transactionIds.push(initSignature);
|
|
833
893
|
if (options.debug) {
|
|
834
894
|
console.log(`[FiveSDK] ✅ Optimized initialization completed: ${initSignature}`);
|
|
@@ -911,19 +971,24 @@ options = {}) {
|
|
|
911
971
|
appendTransaction.feePayer = deployerKeypair.publicKey;
|
|
912
972
|
appendTransaction.recentBlockhash = appendBlockhash.blockhash;
|
|
913
973
|
appendTransaction.partialSign(deployerKeypair);
|
|
914
|
-
const
|
|
915
|
-
|
|
916
|
-
|
|
974
|
+
const appendSend = await sendAndConfirmRawTransactionRobust(connection, appendTransaction.serialize(), {
|
|
975
|
+
commitment: bootstrapCommitment,
|
|
976
|
+
timeoutMs: 120000,
|
|
977
|
+
debug: options.debug,
|
|
917
978
|
maxRetries: options.maxRetries || 3,
|
|
979
|
+
skipPreflight: false,
|
|
980
|
+
preflightCommitment: "confirmed",
|
|
981
|
+
blockhash: appendBlockhash.blockhash,
|
|
982
|
+
lastValidBlockHeight: appendBlockhash.lastValidBlockHeight,
|
|
918
983
|
});
|
|
919
|
-
|
|
920
|
-
if (!appendConfirmation.success) {
|
|
984
|
+
if (!appendSend.success || !appendSend.signature) {
|
|
921
985
|
return {
|
|
922
986
|
success: false,
|
|
923
|
-
error: `Append confirmation failed: ${
|
|
987
|
+
error: `Append confirmation failed: ${appendSend.error}`,
|
|
924
988
|
transactionIds
|
|
925
989
|
};
|
|
926
990
|
}
|
|
991
|
+
const appendSignature = appendSend.signature;
|
|
927
992
|
transactionIds.push(appendSignature);
|
|
928
993
|
if (options.debug) {
|
|
929
994
|
console.log(`[FiveSDK] ✅ Multi-chunk append completed: ${appendSignature}`);
|
|
@@ -957,17 +1022,20 @@ options = {}) {
|
|
|
957
1022
|
const finalizeBlockhash = await connection.getLatestBlockhash("confirmed");
|
|
958
1023
|
finalizeTransaction.recentBlockhash = finalizeBlockhash.blockhash;
|
|
959
1024
|
finalizeTransaction.partialSign(deployerKeypair);
|
|
960
|
-
const
|
|
961
|
-
|
|
962
|
-
|
|
1025
|
+
const finalizeSend = await sendAndConfirmRawTransactionRobust(connection, finalizeTransaction.serialize(), {
|
|
1026
|
+
commitment: bootstrapCommitment,
|
|
1027
|
+
timeoutMs: 120000,
|
|
1028
|
+
debug: options.debug,
|
|
963
1029
|
maxRetries: options.maxRetries || 3,
|
|
1030
|
+
skipPreflight: false,
|
|
1031
|
+
preflightCommitment: "confirmed",
|
|
1032
|
+
blockhash: finalizeBlockhash.blockhash,
|
|
1033
|
+
lastValidBlockHeight: finalizeBlockhash.lastValidBlockHeight,
|
|
964
1034
|
});
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
options.debug);
|
|
968
|
-
if (!finalizeConfirmation.success) {
|
|
969
|
-
console.error(`[FiveSDK] FinalizeScript confirmation failed: ${finalizeConfirmation.error}`);
|
|
1035
|
+
if (!finalizeSend.success || !finalizeSend.signature) {
|
|
1036
|
+
console.error(`[FiveSDK] FinalizeScript confirmation failed: ${finalizeSend.error}`);
|
|
970
1037
|
}
|
|
1038
|
+
const finalizeSignature = finalizeSend.signature;
|
|
971
1039
|
transactionIds.push(finalizeSignature);
|
|
972
1040
|
if (options.debug) {
|
|
973
1041
|
console.log(`[FiveSDK] ✅ FinalizeScript completed: ${finalizeSignature}`);
|
|
@@ -1090,7 +1158,8 @@ async function ensureCanonicalVmStateAccount(connection, deployerKeypair, progra
|
|
|
1090
1158
|
throw new Error(`vmStateAccount must be canonical PDA ${canonical.address}; got ${options.vmStateAccount}`);
|
|
1091
1159
|
}
|
|
1092
1160
|
const vmStatePubkey = new PublicKey(canonical.address);
|
|
1093
|
-
const
|
|
1161
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
|
|
1162
|
+
const existing = await connection.getAccountInfo(vmStatePubkey, bootstrapCommitment);
|
|
1094
1163
|
if (existing) {
|
|
1095
1164
|
if (existing.owner.toBase58() !== programId.toBase58()) {
|
|
1096
1165
|
throw new Error(`canonical VM state ${canonical.address} exists but is owned by ${existing.owner.toBase58()}, expected ${programId.toBase58()}`);
|
|
@@ -1120,14 +1189,18 @@ async function ensureCanonicalVmStateAccount(connection, deployerKeypair, progra
|
|
|
1120
1189
|
const initBlockhash = await connection.getLatestBlockhash("confirmed");
|
|
1121
1190
|
initTransaction.recentBlockhash = initBlockhash.blockhash;
|
|
1122
1191
|
initTransaction.partialSign(deployerKeypair);
|
|
1123
|
-
const
|
|
1124
|
-
|
|
1125
|
-
|
|
1192
|
+
const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
|
|
1193
|
+
commitment: "confirmed",
|
|
1194
|
+
timeoutMs: 120000,
|
|
1195
|
+
debug: options.debug,
|
|
1126
1196
|
maxRetries: options.maxRetries || 3,
|
|
1197
|
+
skipPreflight: false,
|
|
1198
|
+
preflightCommitment: "confirmed",
|
|
1199
|
+
blockhash: initBlockhash.blockhash,
|
|
1200
|
+
lastValidBlockHeight: initBlockhash.lastValidBlockHeight,
|
|
1127
1201
|
});
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
throw new Error(`canonical VM state initialization failed: ${initConfirmation.error || JSON.stringify(initConfirmation.err)}`);
|
|
1202
|
+
if (!initSend.success || initSend.err) {
|
|
1203
|
+
throw new Error(`canonical VM state initialization failed: ${initSend.error || JSON.stringify(initSend.err)}`);
|
|
1131
1204
|
}
|
|
1132
1205
|
return { vmStatePubkey, vmStateRent, created: true, bump: canonical.bump };
|
|
1133
1206
|
}
|
|
@@ -65,6 +65,11 @@ export declare function executeOnSolana(scriptAccount: string, connection: any,
|
|
|
65
65
|
vmStateAccount?: string;
|
|
66
66
|
fiveVMProgramId?: string;
|
|
67
67
|
abi?: any;
|
|
68
|
+
accountMetadata?: Map<string, {
|
|
69
|
+
isSigner: boolean;
|
|
70
|
+
isWritable: boolean;
|
|
71
|
+
isSystemAccount?: boolean;
|
|
72
|
+
}>;
|
|
68
73
|
feeShardIndex?: number;
|
|
69
74
|
payerAccount?: string;
|
|
70
75
|
}): Promise<{
|