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