@5ive-tech/sdk 1.1.13 → 1.1.15
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 +22 -0
- package/dist/FiveSDK.d.ts +43 -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/bin/gen-types.js +0 -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/config/ProgramIdResolver.js +6 -2
- 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 +167 -98
- package/dist/modules/execute.d.ts +5 -0
- package/dist/modules/execute.js +109 -50
- 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/TypeGenerator.js +8 -1
- package/dist/project/config.js +113 -1
- package/dist/project/workspace.d.ts +5 -0
- package/dist/testing/AccountTestFixture.js +3 -3
- 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 +17 -6
- package/dist/types.js +2 -1
- 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/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;
|
|
@@ -12,13 +13,28 @@ const DEFAULT_FEE_VAULT_SHARD_COUNT = (() => {
|
|
|
12
13
|
return 2;
|
|
13
14
|
}
|
|
14
15
|
})();
|
|
16
|
+
const MAX_FEE_VAULT_SHARD_COUNT = 8;
|
|
15
17
|
const FEE_VAULT_NAMESPACE_SEED = Buffer.from([
|
|
16
18
|
0xff, 0x66, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x6d, 0x5f, 0x66, 0x65, 0x65,
|
|
17
19
|
0x5f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x31,
|
|
18
20
|
]);
|
|
19
21
|
function clampShardCount(rawCount) {
|
|
20
22
|
const normalized = rawCount > 0 ? rawCount : DEFAULT_FEE_VAULT_SHARD_COUNT;
|
|
21
|
-
return Math.max(1, Math.min(
|
|
23
|
+
return Math.max(1, Math.min(MAX_FEE_VAULT_SHARD_COUNT, normalized));
|
|
24
|
+
}
|
|
25
|
+
function normalizeRpcEndpoint(connection) {
|
|
26
|
+
return String(connection?.rpcEndpoint || connection?._rpcEndpoint || "").toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
function isLocalnetBootstrapConnection(connection, network) {
|
|
29
|
+
const normalizedNetwork = String(network || "").toLowerCase();
|
|
30
|
+
if (normalizedNetwork === "localnet") {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
const endpoint = normalizeRpcEndpoint(connection);
|
|
34
|
+
return endpoint.includes("127.0.0.1") || endpoint.includes("localhost");
|
|
35
|
+
}
|
|
36
|
+
function selectBootstrapCommitment(connection, network) {
|
|
37
|
+
return isLocalnetBootstrapConnection(connection, network) ? "confirmed" : "finalized";
|
|
22
38
|
}
|
|
23
39
|
async function readVMStateFeeConfig(connection, vmStateAddress) {
|
|
24
40
|
if (!connection) {
|
|
@@ -53,6 +69,25 @@ async function deriveProgramFeeVault(programId, shardIndex) {
|
|
|
53
69
|
const [pda, bump] = PublicKey.findProgramAddressSync([FEE_VAULT_NAMESPACE_SEED, Buffer.from([shardIndex])], new PublicKey(programId));
|
|
54
70
|
return { address: pda.toBase58(), bump };
|
|
55
71
|
}
|
|
72
|
+
async function resolveScriptAccountDerivation(bytecode, deployer, programId, options) {
|
|
73
|
+
const { PublicKey } = await import("@solana/web3.js");
|
|
74
|
+
if (options.scriptAccount) {
|
|
75
|
+
validator.validateBase58Address(options.scriptAccount, "options.scriptAccount");
|
|
76
|
+
if (!options.scriptSeed) {
|
|
77
|
+
throw new Error("options.scriptSeed is required when options.scriptAccount is provided");
|
|
78
|
+
}
|
|
79
|
+
const expectedAccount = await PublicKey.createWithSeed(new PublicKey(deployer), options.scriptSeed, new PublicKey(programId));
|
|
80
|
+
if (expectedAccount.toBase58() !== options.scriptAccount) {
|
|
81
|
+
throw new Error("options.scriptAccount does not match the derived address for the provided deployer, scriptSeed, and programId");
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
address: options.scriptAccount,
|
|
85
|
+
bump: 0,
|
|
86
|
+
seed: options.scriptSeed,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return PDAUtils.deriveScriptAccount(bytecode, deployer, programId);
|
|
90
|
+
}
|
|
56
91
|
function createInitFeeVaultInstructionData(shardIndex, bump) {
|
|
57
92
|
return Uint8Array.from([11, shardIndex & 0xff, bump & 0xff]);
|
|
58
93
|
}
|
|
@@ -60,10 +95,24 @@ async function initProgramFeeVaultShards(connection, programId, vmStateAccount,
|
|
|
60
95
|
const { PublicKey, Transaction, TransactionInstruction, SystemProgram } = await import("@solana/web3.js");
|
|
61
96
|
const signatures = [];
|
|
62
97
|
const effectiveShardCount = clampShardCount(shardCount);
|
|
98
|
+
const programPubkey = new PublicKey(programId);
|
|
99
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection);
|
|
63
100
|
for (let shardIndex = 0; shardIndex < effectiveShardCount; shardIndex++) {
|
|
64
101
|
const vault = await deriveProgramFeeVault(programId, shardIndex);
|
|
102
|
+
const existingVault = await getAccountInfoWithRetry(connection, new PublicKey(vault.address), {
|
|
103
|
+
commitment: bootstrapCommitment,
|
|
104
|
+
retries: 1,
|
|
105
|
+
delayMs: 500,
|
|
106
|
+
debug: options.debug,
|
|
107
|
+
});
|
|
108
|
+
if (existingVault?.owner && new PublicKey(existingVault.owner).equals(programPubkey)) {
|
|
109
|
+
if (options.debug) {
|
|
110
|
+
console.log(`[FiveSDK] Fee vault shard ${shardIndex} already initialized: ${vault.address}`);
|
|
111
|
+
}
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
65
114
|
const tx = new Transaction().add(new TransactionInstruction({
|
|
66
|
-
programId:
|
|
115
|
+
programId: programPubkey,
|
|
67
116
|
keys: [
|
|
68
117
|
{ pubkey: new PublicKey(vmStateAccount), isSigner: false, isWritable: false },
|
|
69
118
|
{ pubkey: payer.publicKey, isSigner: true, isWritable: true },
|
|
@@ -72,24 +121,24 @@ async function initProgramFeeVaultShards(connection, programId, vmStateAccount,
|
|
|
72
121
|
],
|
|
73
122
|
data: Buffer.from(createInitFeeVaultInstructionData(shardIndex, vault.bump)),
|
|
74
123
|
}));
|
|
75
|
-
const
|
|
76
|
-
tx.recentBlockhash = blockhash;
|
|
124
|
+
const latestBlockhash = await connection.getLatestBlockhash("confirmed");
|
|
125
|
+
tx.recentBlockhash = latestBlockhash.blockhash;
|
|
77
126
|
tx.feePayer = payer.publicKey;
|
|
78
127
|
tx.partialSign(payer);
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
preflightCommitment: "confirmed",
|
|
82
|
-
maxRetries: options.maxRetries || 3,
|
|
83
|
-
});
|
|
84
|
-
const shardConfirm = await confirmTransactionRobust(connection, sig, {
|
|
85
|
-
commitment: "finalized",
|
|
128
|
+
const shardSend = await sendAndConfirmRawTransactionRobust(connection, tx.serialize(), {
|
|
129
|
+
commitment: bootstrapCommitment,
|
|
86
130
|
timeoutMs: 120000,
|
|
87
131
|
debug: options.debug,
|
|
132
|
+
maxRetries: options.maxRetries || 3,
|
|
133
|
+
skipPreflight: false,
|
|
134
|
+
preflightCommitment: "confirmed",
|
|
135
|
+
blockhash: latestBlockhash.blockhash,
|
|
136
|
+
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
|
|
88
137
|
});
|
|
89
|
-
if (!
|
|
90
|
-
throw new Error(`Fee vault shard init failed: ${
|
|
138
|
+
if (!shardSend.success || !shardSend.signature) {
|
|
139
|
+
throw new Error(`Fee vault shard init failed: ${shardSend.error || "unconfirmed"}`);
|
|
91
140
|
}
|
|
92
|
-
signatures.push(
|
|
141
|
+
signatures.push(shardSend.signature);
|
|
93
142
|
if (options.debug) {
|
|
94
143
|
console.log(`[FiveSDK] Initialized fee vault shard ${shardIndex}: ${vault.address}`);
|
|
95
144
|
}
|
|
@@ -100,9 +149,6 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
|
|
|
100
149
|
Validators.bytecode(bytecode);
|
|
101
150
|
validator.validateBase58Address(deployer, "deployer");
|
|
102
151
|
Validators.options(options);
|
|
103
|
-
if (options.scriptAccount) {
|
|
104
|
-
validator.validateBase58Address(options.scriptAccount, "options.scriptAccount");
|
|
105
|
-
}
|
|
106
152
|
// Resolve program ID with consistent precedence
|
|
107
153
|
const programId = ProgramIdResolver.resolve(fiveVMProgramId || options.fiveVMProgramId);
|
|
108
154
|
const exportMetadata = encodeExportMetadata(options.exportMetadata);
|
|
@@ -110,7 +156,7 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
|
|
|
110
156
|
console.log(`[FiveSDK] Generating deployment transaction (${bytecode.length} bytes)...`);
|
|
111
157
|
console.log(`[FiveSDK] Using program ID: ${programId}`);
|
|
112
158
|
}
|
|
113
|
-
const scriptResult = await
|
|
159
|
+
const scriptResult = await resolveScriptAccountDerivation(bytecode, deployer, programId, options);
|
|
114
160
|
const scriptAccount = scriptResult.address;
|
|
115
161
|
const scriptSeed = scriptResult.seed;
|
|
116
162
|
const vmStatePDAResult = await PDAUtils.deriveVMStatePDA(programId);
|
|
@@ -119,9 +165,8 @@ export async function generateDeployInstruction(bytecode, deployer, options = {}
|
|
|
119
165
|
console.log(`[FiveSDK] Script Account: ${scriptAccount} (seed: ${scriptSeed})`);
|
|
120
166
|
console.log(`[FiveSDK] VM State PDA: ${vmStatePDA}`);
|
|
121
167
|
}
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
const rentLamports = await RentCalculator.calculateRentExemption(totalAccountSize);
|
|
168
|
+
const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
|
|
169
|
+
const rentLamports = await RentCalculator.calculateRentExemptionWithConnection(totalAccountSize, connection);
|
|
125
170
|
const { deployFeeLamports } = await readVMStateFeeConfig(connection, vmStatePDA);
|
|
126
171
|
const deployShardIndex = 0;
|
|
127
172
|
const deployVault = await deriveProgramFeeVault(programId, deployShardIndex);
|
|
@@ -196,9 +241,8 @@ options = {}) {
|
|
|
196
241
|
const scriptKeypair = Keypair.generate();
|
|
197
242
|
const scriptAccount = scriptKeypair.publicKey.toString();
|
|
198
243
|
// Calculate account size and rent
|
|
199
|
-
const SCRIPT_HEADER_SIZE = 64; // ScriptHeader::LEN
|
|
200
244
|
const exportMetadata = encodeExportMetadata(options.exportMetadata);
|
|
201
|
-
const totalAccountSize =
|
|
245
|
+
const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
|
|
202
246
|
const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
|
|
203
247
|
const vmStatePDA = await PDAUtils.deriveVMStatePDA(programIdStr);
|
|
204
248
|
const vmStatePubkey = new PublicKey(vmStatePDA.address);
|
|
@@ -216,7 +260,8 @@ options = {}) {
|
|
|
216
260
|
}));
|
|
217
261
|
}
|
|
218
262
|
// 1. Initialize canonical VM State if missing
|
|
219
|
-
const
|
|
263
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection);
|
|
264
|
+
const vmStateInfo = await connection.getAccountInfo(vmStatePubkey, bootstrapCommitment);
|
|
220
265
|
if (!vmStateInfo) {
|
|
221
266
|
tx.add(new TransactionInstruction({
|
|
222
267
|
keys: [
|
|
@@ -280,17 +325,18 @@ options = {}) {
|
|
|
280
325
|
console.log(`[FiveSDK] Generated script keypair: ${scriptAccount}`);
|
|
281
326
|
}
|
|
282
327
|
// Calculate account size and rent
|
|
283
|
-
const SCRIPT_HEADER_SIZE = 64; // ScriptHeader::LEN (five-protocol)
|
|
284
328
|
const exportMetadata = encodeExportMetadata(options.exportMetadata);
|
|
285
|
-
const totalAccountSize =
|
|
329
|
+
const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + exportMetadata.length + bytecode.length;
|
|
286
330
|
const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
|
|
287
331
|
const vmStateResolution = await ensureCanonicalVmStateAccount(connection, deployerKeypair, new PublicKey(programId), {
|
|
288
332
|
vmStateAccount: options.vmStateAccount,
|
|
289
333
|
maxRetries: options.maxRetries,
|
|
290
334
|
debug: options.debug,
|
|
335
|
+
network: options.network,
|
|
291
336
|
});
|
|
292
337
|
const vmStatePubkey = vmStateResolution.vmStatePubkey;
|
|
293
338
|
const vmStateRent = vmStateResolution.vmStateRent;
|
|
339
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
|
|
294
340
|
const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
|
|
295
341
|
const deployShardIndex = 0;
|
|
296
342
|
const deployVault = await deriveProgramFeeVault(programId, deployShardIndex);
|
|
@@ -313,7 +359,7 @@ options = {}) {
|
|
|
313
359
|
console.log(`[FiveSDK] Export metadata size: ${exportMetadata.length} bytes`);
|
|
314
360
|
console.log(`[FiveSDK] Rent cost: ${((rentLamports + vmStateRent) / 1e9)} SOL`);
|
|
315
361
|
}
|
|
316
|
-
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programId, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries });
|
|
362
|
+
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programId, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries, network: options.network });
|
|
317
363
|
// SINGLE TRANSACTION: create script account + deploy bytecode
|
|
318
364
|
const tx = new Transaction();
|
|
319
365
|
// Optional compute budget
|
|
@@ -378,19 +424,20 @@ options = {}) {
|
|
|
378
424
|
if (options.debug) {
|
|
379
425
|
console.log(`[FiveSDK] Transaction serialized: ${txSerialized.length} bytes`);
|
|
380
426
|
}
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
427
|
+
const sendResult = await sendAndConfirmRawTransactionRobust(connection, txSerialized, {
|
|
428
|
+
commitment: "confirmed",
|
|
429
|
+
timeoutMs: 120000,
|
|
430
|
+
debug: options.debug,
|
|
384
431
|
maxRetries: options.maxRetries || 3,
|
|
432
|
+
skipPreflight: false,
|
|
433
|
+
preflightCommitment: "confirmed",
|
|
385
434
|
});
|
|
435
|
+
const signature = sendResult.signature;
|
|
386
436
|
if (options.debug) {
|
|
387
437
|
console.log(`[FiveSDK] sendRawTransaction completed, returned signature: ${signature}`);
|
|
388
438
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
options.debug);
|
|
392
|
-
if (!confirmationResult.success) {
|
|
393
|
-
const errorMessage = `Deployment confirmation failed: ${confirmationResult.error || "Unknown error"}`;
|
|
439
|
+
if (!sendResult.success || !signature) {
|
|
440
|
+
const errorMessage = `Deployment confirmation failed: ${sendResult.error || "Unknown error"}`;
|
|
394
441
|
if (options.debug)
|
|
395
442
|
console.log(`[FiveSDK] ${errorMessage}`);
|
|
396
443
|
return {
|
|
@@ -399,8 +446,8 @@ options = {}) {
|
|
|
399
446
|
transactionId: signature,
|
|
400
447
|
};
|
|
401
448
|
}
|
|
402
|
-
if (
|
|
403
|
-
const errorMessage = `Combined deployment failed: ${JSON.stringify(
|
|
449
|
+
if (sendResult.err) {
|
|
450
|
+
const errorMessage = `Combined deployment failed: ${JSON.stringify(sendResult.err)}`;
|
|
404
451
|
if (options.debug)
|
|
405
452
|
console.log(`[FiveSDK] ${errorMessage}`);
|
|
406
453
|
return {
|
|
@@ -468,8 +515,7 @@ options = {}) {
|
|
|
468
515
|
const scriptKeypair = Keypair.generate();
|
|
469
516
|
const scriptAccount = scriptKeypair.publicKey.toString();
|
|
470
517
|
// Calculate account size and rent
|
|
471
|
-
const
|
|
472
|
-
const totalAccountSize = SCRIPT_HEADER_SIZE + bytecode.length;
|
|
518
|
+
const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
|
|
473
519
|
const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
|
|
474
520
|
const programIdStr = ProgramIdResolver.resolve(options.fiveVMProgramId);
|
|
475
521
|
const programId = new PublicKey(programIdStr);
|
|
@@ -477,9 +523,11 @@ options = {}) {
|
|
|
477
523
|
vmStateAccount: options.vmStateAccount,
|
|
478
524
|
maxRetries: options.maxRetries,
|
|
479
525
|
debug: options.debug,
|
|
526
|
+
network: options.network,
|
|
480
527
|
});
|
|
481
528
|
const vmStatePubkey = vmStateResolution.vmStatePubkey;
|
|
482
529
|
const vmStateRent = vmStateResolution.vmStateRent;
|
|
530
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
|
|
483
531
|
const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
|
|
484
532
|
const deployShardIndex = 0;
|
|
485
533
|
const deployVault = await deriveProgramFeeVault(programIdStr, deployShardIndex);
|
|
@@ -501,7 +549,7 @@ options = {}) {
|
|
|
501
549
|
console.log(`[FiveSDK] Total account size: ${totalAccountSize} bytes`);
|
|
502
550
|
console.log(`[FiveSDK] Initial rent cost: ${(rentLamports + vmStateRent) / 1e9} SOL`);
|
|
503
551
|
}
|
|
504
|
-
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries });
|
|
552
|
+
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries, network: options.network });
|
|
505
553
|
const transactionIds = [];
|
|
506
554
|
let totalCost = rentLamports + vmStateRent;
|
|
507
555
|
// TRANSACTION 1: Create Account + InitLargeProgram
|
|
@@ -514,7 +562,7 @@ options = {}) {
|
|
|
514
562
|
fromPubkey: deployerKeypair.publicKey,
|
|
515
563
|
newAccountPubkey: scriptKeypair.publicKey,
|
|
516
564
|
lamports: rentLamports,
|
|
517
|
-
space:
|
|
565
|
+
space: SCRIPT_ACCOUNT_HEADER_LEN, // Start with just the ScriptAccountHeader
|
|
518
566
|
programId: programId,
|
|
519
567
|
});
|
|
520
568
|
initTransaction.add(createAccountInstruction);
|
|
@@ -535,7 +583,7 @@ options = {}) {
|
|
|
535
583
|
{
|
|
536
584
|
pubkey: vmStatePubkey,
|
|
537
585
|
isSigner: false,
|
|
538
|
-
isWritable:
|
|
586
|
+
isWritable: true,
|
|
539
587
|
},
|
|
540
588
|
...feeVaultKeys,
|
|
541
589
|
],
|
|
@@ -545,23 +593,24 @@ options = {}) {
|
|
|
545
593
|
initTransaction.add(initLargeProgramInstruction);
|
|
546
594
|
// Sign and send initialization transaction
|
|
547
595
|
initTransaction.feePayer = deployerKeypair.publicKey;
|
|
548
|
-
const
|
|
549
|
-
initTransaction.recentBlockhash = blockhash;
|
|
596
|
+
const initBlockhash = await connection.getLatestBlockhash("confirmed");
|
|
597
|
+
initTransaction.recentBlockhash = initBlockhash.blockhash;
|
|
550
598
|
initTransaction.partialSign(deployerKeypair);
|
|
551
599
|
initTransaction.partialSign(scriptKeypair);
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
preflightCommitment: "confirmed",
|
|
555
|
-
maxRetries: options.maxRetries || 3,
|
|
556
|
-
});
|
|
557
|
-
const initConfirm = await confirmTransactionRobust(connection, initSignature, {
|
|
558
|
-
commitment: "finalized",
|
|
600
|
+
const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
|
|
601
|
+
commitment: bootstrapCommitment,
|
|
559
602
|
timeoutMs: 120000,
|
|
560
603
|
debug: options.debug,
|
|
604
|
+
maxRetries: options.maxRetries || 3,
|
|
605
|
+
skipPreflight: false,
|
|
606
|
+
preflightCommitment: "confirmed",
|
|
607
|
+
blockhash: initBlockhash.blockhash,
|
|
608
|
+
lastValidBlockHeight: initBlockhash.lastValidBlockHeight,
|
|
561
609
|
});
|
|
562
|
-
if (!
|
|
563
|
-
throw new Error(`Initialization confirmation failed: ${
|
|
610
|
+
if (!initSend.success || !initSend.signature) {
|
|
611
|
+
throw new Error(`Initialization confirmation failed: ${initSend.error || "unconfirmed"}`);
|
|
564
612
|
}
|
|
613
|
+
const initSignature = initSend.signature;
|
|
565
614
|
transactionIds.push(initSignature);
|
|
566
615
|
if (options.debug) {
|
|
567
616
|
console.log(`[FiveSDK] ✅ Initialization completed: ${initSignature}`);
|
|
@@ -580,7 +629,7 @@ options = {}) {
|
|
|
580
629
|
console.log(`[FiveSDK] Step ${i + 2}: Appending chunk ${i + 1}/${chunks.length} (${chunk.length} bytes)`);
|
|
581
630
|
}
|
|
582
631
|
// Calculate additional rent needed for this chunk
|
|
583
|
-
const currentInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, { commitment:
|
|
632
|
+
const currentInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, { commitment: bootstrapCommitment, retries: 2, delayMs: 1000, debug: options.debug });
|
|
584
633
|
if (!currentInfo)
|
|
585
634
|
throw new Error("Script account not found after initialization");
|
|
586
635
|
const newSize = currentInfo.data.length + chunk.length;
|
|
@@ -633,7 +682,7 @@ options = {}) {
|
|
|
633
682
|
{
|
|
634
683
|
pubkey: vmStatePubkey,
|
|
635
684
|
isSigner: false,
|
|
636
|
-
isWritable:
|
|
685
|
+
isWritable: true,
|
|
637
686
|
},
|
|
638
687
|
...feeVaultKeys,
|
|
639
688
|
],
|
|
@@ -646,19 +695,20 @@ options = {}) {
|
|
|
646
695
|
appendTransaction.feePayer = deployerKeypair.publicKey;
|
|
647
696
|
appendTransaction.recentBlockhash = appendBlockhash.blockhash;
|
|
648
697
|
appendTransaction.partialSign(deployerKeypair);
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
preflightCommitment: "confirmed",
|
|
652
|
-
maxRetries: options.maxRetries || 3,
|
|
653
|
-
});
|
|
654
|
-
const appendConfirm = await confirmTransactionRobust(connection, appendSignature, {
|
|
655
|
-
commitment: "finalized",
|
|
698
|
+
const appendSend = await sendAndConfirmRawTransactionRobust(connection, appendTransaction.serialize(), {
|
|
699
|
+
commitment: bootstrapCommitment,
|
|
656
700
|
timeoutMs: 120000,
|
|
657
701
|
debug: options.debug,
|
|
702
|
+
maxRetries: options.maxRetries || 3,
|
|
703
|
+
skipPreflight: false,
|
|
704
|
+
preflightCommitment: "confirmed",
|
|
705
|
+
blockhash: appendBlockhash.blockhash,
|
|
706
|
+
lastValidBlockHeight: appendBlockhash.lastValidBlockHeight,
|
|
658
707
|
});
|
|
659
|
-
if (!
|
|
660
|
-
throw new Error(`Append confirmation failed: ${
|
|
708
|
+
if (!appendSend.success || !appendSend.signature) {
|
|
709
|
+
throw new Error(`Append confirmation failed: ${appendSend.error || "unconfirmed"}`);
|
|
661
710
|
}
|
|
711
|
+
const appendSignature = appendSend.signature;
|
|
662
712
|
transactionIds.push(appendSignature);
|
|
663
713
|
if (options.debug) {
|
|
664
714
|
console.log(`[FiveSDK] ✅ Chunk ${i + 1} appended: ${appendSignature}`);
|
|
@@ -666,7 +716,7 @@ options = {}) {
|
|
|
666
716
|
}
|
|
667
717
|
// Final verification
|
|
668
718
|
let finalInfo = await getAccountInfoWithRetry(connection, scriptKeypair.publicKey, {
|
|
669
|
-
commitment:
|
|
719
|
+
commitment: bootstrapCommitment,
|
|
670
720
|
retries: 2,
|
|
671
721
|
delayMs: 1000,
|
|
672
722
|
debug: options.debug,
|
|
@@ -674,7 +724,7 @@ options = {}) {
|
|
|
674
724
|
if (!finalInfo) {
|
|
675
725
|
throw new Error("Script account not found during final verification");
|
|
676
726
|
}
|
|
677
|
-
const expectedSize =
|
|
727
|
+
const expectedSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
|
|
678
728
|
if (options.debug) {
|
|
679
729
|
console.log(`[FiveSDK] 🔍 Final verification:`);
|
|
680
730
|
console.log(`[FiveSDK] Expected size: ${expectedSize} bytes`);
|
|
@@ -738,8 +788,7 @@ options = {}) {
|
|
|
738
788
|
const scriptKeypair = Keypair.generate();
|
|
739
789
|
const scriptAccount = scriptKeypair.publicKey.toString();
|
|
740
790
|
// Calculate full account size upfront
|
|
741
|
-
const
|
|
742
|
-
const totalAccountSize = SCRIPT_HEADER_SIZE + bytecode.length;
|
|
791
|
+
const totalAccountSize = SCRIPT_ACCOUNT_HEADER_LEN + bytecode.length;
|
|
743
792
|
const rentLamports = await connection.getMinimumBalanceForRentExemption(totalAccountSize);
|
|
744
793
|
const programIdStr = ProgramIdResolver.resolve(options.fiveVMProgramId);
|
|
745
794
|
const programId = new PublicKey(programIdStr);
|
|
@@ -747,9 +796,11 @@ options = {}) {
|
|
|
747
796
|
vmStateAccount: options.vmStateAccount,
|
|
748
797
|
maxRetries: options.maxRetries,
|
|
749
798
|
debug: options.debug,
|
|
799
|
+
network: options.network,
|
|
750
800
|
});
|
|
751
801
|
const vmStatePubkey = vmStateResolution.vmStatePubkey;
|
|
752
802
|
const vmStateRent = vmStateResolution.vmStateRent;
|
|
803
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
|
|
753
804
|
const vmStateFeeConfig = await readVMStateFeeConfig(connection, vmStatePubkey.toString());
|
|
754
805
|
const deployShardIndex = 0;
|
|
755
806
|
const deployVault = await deriveProgramFeeVault(programIdStr, deployShardIndex);
|
|
@@ -771,7 +822,7 @@ options = {}) {
|
|
|
771
822
|
console.log(`[FiveSDK] PRE-ALLOCATED full account size: ${totalAccountSize} bytes`);
|
|
772
823
|
console.log(`[FiveSDK] Full rent cost paid upfront: ${(rentLamports + vmStateRent) / 1e9} SOL`);
|
|
773
824
|
}
|
|
774
|
-
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries });
|
|
825
|
+
const feeVaultInitSigs = await initProgramFeeVaultShards(connection, programIdStr, vmStatePubkey.toString(), vmStateFeeConfig.shardCount, deployerKeypair, { debug: options.debug, maxRetries: options.maxRetries, network: options.network });
|
|
775
826
|
const transactionIds = [];
|
|
776
827
|
let totalCost = rentLamports + vmStateRent;
|
|
777
828
|
const chunks = chunkBytecode(bytecode, chunkSize);
|
|
@@ -808,7 +859,7 @@ options = {}) {
|
|
|
808
859
|
{
|
|
809
860
|
pubkey: vmStatePubkey,
|
|
810
861
|
isSigner: false,
|
|
811
|
-
isWritable:
|
|
862
|
+
isWritable: true,
|
|
812
863
|
},
|
|
813
864
|
...feeVaultKeys,
|
|
814
865
|
],
|
|
@@ -821,19 +872,24 @@ options = {}) {
|
|
|
821
872
|
initTransaction.recentBlockhash = blockhash;
|
|
822
873
|
initTransaction.partialSign(deployerKeypair);
|
|
823
874
|
initTransaction.partialSign(scriptKeypair);
|
|
824
|
-
const
|
|
825
|
-
|
|
826
|
-
|
|
875
|
+
const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
|
|
876
|
+
commitment: "confirmed",
|
|
877
|
+
timeoutMs: 120000,
|
|
878
|
+
debug: options.debug,
|
|
827
879
|
maxRetries: options.maxRetries || 3,
|
|
880
|
+
skipPreflight: false,
|
|
881
|
+
preflightCommitment: "confirmed",
|
|
882
|
+
blockhash: blockhash,
|
|
883
|
+
lastValidBlockHeight: undefined,
|
|
828
884
|
});
|
|
829
|
-
|
|
830
|
-
if (!initConfirmation.success) {
|
|
885
|
+
if (!initSend.success || !initSend.signature) {
|
|
831
886
|
return {
|
|
832
887
|
success: false,
|
|
833
|
-
error: `Initialization confirmation failed: ${
|
|
888
|
+
error: `Initialization confirmation failed: ${initSend.error}`,
|
|
834
889
|
transactionIds
|
|
835
890
|
};
|
|
836
891
|
}
|
|
892
|
+
const initSignature = initSend.signature;
|
|
837
893
|
transactionIds.push(initSignature);
|
|
838
894
|
if (options.debug) {
|
|
839
895
|
console.log(`[FiveSDK] ✅ Optimized initialization completed: ${initSignature}`);
|
|
@@ -916,19 +972,24 @@ options = {}) {
|
|
|
916
972
|
appendTransaction.feePayer = deployerKeypair.publicKey;
|
|
917
973
|
appendTransaction.recentBlockhash = appendBlockhash.blockhash;
|
|
918
974
|
appendTransaction.partialSign(deployerKeypair);
|
|
919
|
-
const
|
|
920
|
-
|
|
921
|
-
|
|
975
|
+
const appendSend = await sendAndConfirmRawTransactionRobust(connection, appendTransaction.serialize(), {
|
|
976
|
+
commitment: bootstrapCommitment,
|
|
977
|
+
timeoutMs: 120000,
|
|
978
|
+
debug: options.debug,
|
|
922
979
|
maxRetries: options.maxRetries || 3,
|
|
980
|
+
skipPreflight: false,
|
|
981
|
+
preflightCommitment: "confirmed",
|
|
982
|
+
blockhash: appendBlockhash.blockhash,
|
|
983
|
+
lastValidBlockHeight: appendBlockhash.lastValidBlockHeight,
|
|
923
984
|
});
|
|
924
|
-
|
|
925
|
-
if (!appendConfirmation.success) {
|
|
985
|
+
if (!appendSend.success || !appendSend.signature) {
|
|
926
986
|
return {
|
|
927
987
|
success: false,
|
|
928
|
-
error: `Append confirmation failed: ${
|
|
988
|
+
error: `Append confirmation failed: ${appendSend.error}`,
|
|
929
989
|
transactionIds
|
|
930
990
|
};
|
|
931
991
|
}
|
|
992
|
+
const appendSignature = appendSend.signature;
|
|
932
993
|
transactionIds.push(appendSignature);
|
|
933
994
|
if (options.debug) {
|
|
934
995
|
console.log(`[FiveSDK] ✅ Multi-chunk append completed: ${appendSignature}`);
|
|
@@ -962,17 +1023,20 @@ options = {}) {
|
|
|
962
1023
|
const finalizeBlockhash = await connection.getLatestBlockhash("confirmed");
|
|
963
1024
|
finalizeTransaction.recentBlockhash = finalizeBlockhash.blockhash;
|
|
964
1025
|
finalizeTransaction.partialSign(deployerKeypair);
|
|
965
|
-
const
|
|
966
|
-
|
|
967
|
-
|
|
1026
|
+
const finalizeSend = await sendAndConfirmRawTransactionRobust(connection, finalizeTransaction.serialize(), {
|
|
1027
|
+
commitment: bootstrapCommitment,
|
|
1028
|
+
timeoutMs: 120000,
|
|
1029
|
+
debug: options.debug,
|
|
968
1030
|
maxRetries: options.maxRetries || 3,
|
|
1031
|
+
skipPreflight: false,
|
|
1032
|
+
preflightCommitment: "confirmed",
|
|
1033
|
+
blockhash: finalizeBlockhash.blockhash,
|
|
1034
|
+
lastValidBlockHeight: finalizeBlockhash.lastValidBlockHeight,
|
|
969
1035
|
});
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
options.debug);
|
|
973
|
-
if (!finalizeConfirmation.success) {
|
|
974
|
-
console.error(`[FiveSDK] FinalizeScript confirmation failed: ${finalizeConfirmation.error}`);
|
|
1036
|
+
if (!finalizeSend.success || !finalizeSend.signature) {
|
|
1037
|
+
console.error(`[FiveSDK] FinalizeScript confirmation failed: ${finalizeSend.error}`);
|
|
975
1038
|
}
|
|
1039
|
+
const finalizeSignature = finalizeSend.signature;
|
|
976
1040
|
transactionIds.push(finalizeSignature);
|
|
977
1041
|
if (options.debug) {
|
|
978
1042
|
console.log(`[FiveSDK] ✅ FinalizeScript completed: ${finalizeSignature}`);
|
|
@@ -1095,7 +1159,8 @@ async function ensureCanonicalVmStateAccount(connection, deployerKeypair, progra
|
|
|
1095
1159
|
throw new Error(`vmStateAccount must be canonical PDA ${canonical.address}; got ${options.vmStateAccount}`);
|
|
1096
1160
|
}
|
|
1097
1161
|
const vmStatePubkey = new PublicKey(canonical.address);
|
|
1098
|
-
const
|
|
1162
|
+
const bootstrapCommitment = selectBootstrapCommitment(connection, options.network);
|
|
1163
|
+
const existing = await connection.getAccountInfo(vmStatePubkey, bootstrapCommitment);
|
|
1099
1164
|
if (existing) {
|
|
1100
1165
|
if (existing.owner.toBase58() !== programId.toBase58()) {
|
|
1101
1166
|
throw new Error(`canonical VM state ${canonical.address} exists but is owned by ${existing.owner.toBase58()}, expected ${programId.toBase58()}`);
|
|
@@ -1125,14 +1190,18 @@ async function ensureCanonicalVmStateAccount(connection, deployerKeypair, progra
|
|
|
1125
1190
|
const initBlockhash = await connection.getLatestBlockhash("confirmed");
|
|
1126
1191
|
initTransaction.recentBlockhash = initBlockhash.blockhash;
|
|
1127
1192
|
initTransaction.partialSign(deployerKeypair);
|
|
1128
|
-
const
|
|
1129
|
-
|
|
1130
|
-
|
|
1193
|
+
const initSend = await sendAndConfirmRawTransactionRobust(connection, initTransaction.serialize(), {
|
|
1194
|
+
commitment: "confirmed",
|
|
1195
|
+
timeoutMs: 120000,
|
|
1196
|
+
debug: options.debug,
|
|
1131
1197
|
maxRetries: options.maxRetries || 3,
|
|
1198
|
+
skipPreflight: false,
|
|
1199
|
+
preflightCommitment: "confirmed",
|
|
1200
|
+
blockhash: initBlockhash.blockhash,
|
|
1201
|
+
lastValidBlockHeight: initBlockhash.lastValidBlockHeight,
|
|
1132
1202
|
});
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
throw new Error(`canonical VM state initialization failed: ${initConfirmation.error || JSON.stringify(initConfirmation.err)}`);
|
|
1203
|
+
if (!initSend.success || initSend.err) {
|
|
1204
|
+
throw new Error(`canonical VM state initialization failed: ${initSend.error || JSON.stringify(initSend.err)}`);
|
|
1136
1205
|
}
|
|
1137
1206
|
return { vmStatePubkey, vmStateRent, created: true, bump: canonical.bump };
|
|
1138
1207
|
}
|
|
@@ -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<{
|