@5ive-tech/sdk 1.1.12 → 1.1.13

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/dist/FiveSDK.d.ts CHANGED
@@ -172,6 +172,8 @@ export declare class FiveSDK {
172
172
  isWritable: boolean;
173
173
  isSystemAccount?: boolean;
174
174
  }>;
175
+ feeShardIndex?: number;
176
+ payerAccount?: string;
175
177
  }): Promise<SerializedExecution>;
176
178
  static getVMState(connection: any, fiveVMProgramId?: string): Promise<{
177
179
  authority: string;
Binary file
File without changes
@@ -16,6 +16,10 @@ const FEE_VAULT_NAMESPACE_SEED = Buffer.from([
16
16
  0xff, 0x66, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x6d, 0x5f, 0x66, 0x65, 0x65,
17
17
  0x5f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x31,
18
18
  ]);
19
+ function clampShardCount(rawCount) {
20
+ const normalized = rawCount > 0 ? rawCount : DEFAULT_FEE_VAULT_SHARD_COUNT;
21
+ return Math.max(1, Math.min(DEFAULT_FEE_VAULT_SHARD_COUNT, normalized));
22
+ }
19
23
  async function readVMStateFeeConfig(connection, vmStateAddress) {
20
24
  if (!connection) {
21
25
  return { shardCount: DEFAULT_FEE_VAULT_SHARD_COUNT };
@@ -37,7 +41,7 @@ async function readVMStateFeeConfig(connection, vmStateAddress) {
37
41
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
38
42
  const deployFeeLamports = view.getUint32(40, true);
39
43
  const shardCountRaw = data.length > 50 ? data[50] : 0;
40
- const shardCount = shardCountRaw > 0 ? shardCountRaw : DEFAULT_FEE_VAULT_SHARD_COUNT;
44
+ const shardCount = clampShardCount(shardCountRaw);
41
45
  return { deployFeeLamports, shardCount };
42
46
  }
43
47
  catch {
@@ -55,7 +59,8 @@ function createInitFeeVaultInstructionData(shardIndex, bump) {
55
59
  async function initProgramFeeVaultShards(connection, programId, vmStateAccount, shardCount, payer, options = {}) {
56
60
  const { PublicKey, Transaction, TransactionInstruction, SystemProgram } = await import("@solana/web3.js");
57
61
  const signatures = [];
58
- for (let shardIndex = 0; shardIndex < shardCount; shardIndex++) {
62
+ const effectiveShardCount = clampShardCount(shardCount);
63
+ for (let shardIndex = 0; shardIndex < effectiveShardCount; shardIndex++) {
59
64
  const vault = await deriveProgramFeeVault(programId, shardIndex);
60
65
  const tx = new Transaction().add(new TransactionInstruction({
61
66
  programId: new PublicKey(programId),
@@ -23,6 +23,10 @@ const FEE_VAULT_NAMESPACE_SEED = Buffer.from([
23
23
  ]);
24
24
  const EXECUTE_FEE_HEADER_A = 0xff;
25
25
  const EXECUTE_FEE_HEADER_B = 0x53;
26
+ function clampShardCount(rawCount) {
27
+ const normalized = rawCount > 0 ? rawCount : DEFAULT_FEE_VAULT_SHARD_COUNT;
28
+ return Math.max(1, Math.min(DEFAULT_FEE_VAULT_SHARD_COUNT, normalized));
29
+ }
26
30
  async function deriveProgramFeeVault(programId, shardIndex) {
27
31
  const { PublicKey } = await import("@solana/web3.js");
28
32
  const [pda, bump] = PublicKey.findProgramAddressSync([FEE_VAULT_NAMESPACE_SEED, Buffer.from([shardIndex])], new PublicKey(programId));
@@ -43,8 +47,7 @@ async function readVMStateShardCount(connection, vmStateAddress) {
43
47
  const data = new Uint8Array(info.data);
44
48
  if (data.length <= 50)
45
49
  return DEFAULT_FEE_VAULT_SHARD_COUNT;
46
- const shardCount = data[50];
47
- return shardCount > 0 ? shardCount : DEFAULT_FEE_VAULT_SHARD_COUNT;
50
+ return clampShardCount(data[50]);
48
51
  }
49
52
  catch {
50
53
  return DEFAULT_FEE_VAULT_SHARD_COUNT;
@@ -278,7 +281,10 @@ export async function generateExecuteInstruction(scriptAccount, functionName, pa
278
281
  { pubkey: vmState, isSigner: false, isWritable: false },
279
282
  ];
280
283
  const abiAccountMetadata = new Map();
281
- if (funcDef && funcDef.parameters) {
284
+ const hasFullParameterList = !!funcDef &&
285
+ Array.isArray(funcDef.parameters) &&
286
+ parameters.length === funcDef.parameters.length;
287
+ if (funcDef && funcDef.parameters && hasFullParameterList) {
282
288
  // First pass: detect if there's an @init constraint and find the payer
283
289
  let hasInit = false;
284
290
  let payerPubkey;
@@ -325,9 +331,11 @@ export async function generateExecuteInstruction(scriptAccount, functionName, pa
325
331
  // Check both derived ABI metadata and passed-in metadata (from FunctionBuilder)
326
332
  const abiMetadata = abiAccountMetadata.get(acc);
327
333
  const passedMetadata = options.accountMetadata?.get(acc);
328
- const metadata = abiMetadata || passedMetadata;
334
+ const metadata = passedMetadata || abiMetadata;
329
335
  const isSigner = metadata ? metadata.isSigner : false;
330
- const isWritable = metadata ? metadata.isWritable : true;
336
+ const isWritable = metadata
337
+ ? (metadata.isSystemAccount ? false : metadata.isWritable)
338
+ : true;
331
339
  return {
332
340
  pubkey: acc,
333
341
  isSigner,
@@ -29,6 +29,7 @@ export declare class FunctionBuilder {
29
29
  private accountsMap;
30
30
  private argsMap;
31
31
  private resolvedAccounts;
32
+ private vmPayerAccount?;
32
33
  constructor(functionDef: FunctionDefinition, scriptAccount: string, abi: ScriptABI, options: FiveProgramOptions);
33
34
  /**
34
35
  * Specify accounts for this function call
@@ -47,6 +48,13 @@ export declare class FunctionBuilder {
47
48
  * @returns this for method chaining
48
49
  */
49
50
  args(args: Record<string, any>): this;
51
+ /**
52
+ * Override the VM execute-fee payer account for this instruction.
53
+ * This is distinct from the outer transaction fee payer.
54
+ */
55
+ payer(payer: string | {
56
+ toBase58(): string;
57
+ }): this;
50
58
  /**
51
59
  * Build and return serialized instruction data
52
60
  * This is the main method that orchestrates parameter resolution and instruction generation
@@ -62,6 +62,15 @@ export class FunctionBuilder {
62
62
  }
63
63
  return this;
64
64
  }
65
+ /**
66
+ * Override the VM execute-fee payer account for this instruction.
67
+ * This is distinct from the outer transaction fee payer.
68
+ */
69
+ payer(payer) {
70
+ this.vmPayerAccount =
71
+ typeof payer === 'string' ? payer : payer.toBase58();
72
+ return this;
73
+ }
65
74
  /**
66
75
  * Build and return serialized instruction data
67
76
  * This is the main method that orchestrates parameter resolution and instruction generation
@@ -93,7 +102,7 @@ export class FunctionBuilder {
93
102
  // Now validate that all required parameters are provided (including auto-injected ones)
94
103
  this.validateParameters();
95
104
  // Merge parameters in ABI order (accounts first, then data)
96
- const { mergedParams, accountPubkeys } = this.mergeParameters();
105
+ const { mergedParams, argParams, accountPubkeys } = this.mergeParameters();
97
106
  // Append system accounts to the account list (they go at the end)
98
107
  const allAccountPubkeys = [...accountPubkeys, ...systemAccountsList];
99
108
  // Build account metadata from ABI attributes
@@ -105,7 +114,7 @@ export class FunctionBuilder {
105
114
  }
106
115
  // Call existing SDK method to generate instruction
107
116
  // This reuses the proven parameter encoding logic
108
- const instruction = await this.generateInstructionData(mergedParams, allAccountPubkeys, accountMetadata);
117
+ const instruction = await this.generateInstructionData(mergedParams, argParams, allAccountPubkeys, accountMetadata);
109
118
  if (this.options.debug) {
110
119
  console.log(`[FunctionBuilder] Generated instruction:`, instruction);
111
120
  }
@@ -178,6 +187,7 @@ export class FunctionBuilder {
178
187
  */
179
188
  mergeParameters() {
180
189
  const mergedParams = [];
190
+ const argParams = [];
181
191
  const accountPubkeys = [];
182
192
  for (const param of this.functionDef.parameters) {
183
193
  if (param.is_account) {
@@ -196,9 +206,10 @@ export class FunctionBuilder {
196
206
  throw new Error(`Missing argument '${param.name}'`);
197
207
  }
198
208
  mergedParams.push(value);
209
+ argParams.push(value);
199
210
  }
200
211
  }
201
- return { mergedParams, accountPubkeys };
212
+ return { mergedParams, argParams, accountPubkeys };
202
213
  }
203
214
  /**
204
215
  * Build account metadata (isSigner, isWritable) from ABI attributes
@@ -279,14 +290,14 @@ export class FunctionBuilder {
279
290
  * @param accountMetadata - Account metadata (isSigner, isWritable)
280
291
  * @returns SerializedInstruction
281
292
  */
282
- async generateInstructionData(mergedParams, accountList, accountMetadata) {
293
+ async generateInstructionData(mergedParams, argParams, accountList, accountMetadata) {
283
294
  // Account list is already passed in
284
295
  // Dynamically import FiveSDK to avoid circular dependencies
285
296
  const { FiveSDK } = await import('../FiveSDK.js');
286
297
  // Call the SDK's generateExecuteInstruction method.
287
298
  // This handles fixed-size typed execute encoding and parameter validation.
288
299
  const executionResult = await FiveSDK.generateExecuteInstruction(this.scriptAccount, this.functionDef.index, // Use function index directly
289
- mergedParams, // All parameters in merged order
300
+ argParams, // Current VM contract encodes non-account args only
290
301
  accountList, // Account pubkey list
291
302
  undefined, // No connection needed - we have ABI
292
303
  {
@@ -295,6 +306,8 @@ export class FunctionBuilder {
295
306
  fiveVMProgramId: this.options.fiveVMProgramId,
296
307
  vmStateAccount: this.options.vmStateAccount,
297
308
  adminAccount: this.options.feeReceiverAccount,
309
+ payerAccount: this.vmPayerAccount ||
310
+ this.options.provider?.publicKey?.toBase58?.(),
298
311
  accountMetadata: accountMetadata, // Pass account metadata for correct isWritable flags
299
312
  });
300
313
  // Map SDK's instruction format (with 'accounts') to SerializedInstruction format (with 'keys')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5ive-tech/sdk",
3
- "version": "1.1.12",
3
+ "version": "1.1.13",
4
4
  "description": "Client-agnostic TypeScript SDK for Five VM scripts on Solana",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
File without changes