genlayer 0.39.0 → 0.39.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -20078,7 +20078,7 @@ var require_cli_table3 = __commonJS({
20078
20078
  import { program } from "commander";
20079
20079
 
20080
20080
  // package.json
20081
- var version = "0.39.0";
20081
+ var version = "0.39.2";
20082
20082
  var package_default = {
20083
20083
  name: "genlayer",
20084
20084
  version,
@@ -20095,8 +20095,7 @@ var package_default = {
20095
20095
  "test:smoke": "vitest run --config vitest.smoke.config.ts",
20096
20096
  dev: "cross-env NODE_ENV=development node esbuild.config.js",
20097
20097
  build: "cross-env NODE_ENV=production node esbuild.config.js",
20098
- release: "release-it --ci",
20099
- "release-beta": "release-it --ci --preRelease=beta",
20098
+ release: "./scripts/release.sh",
20100
20099
  postinstall: "node ./scripts/postinstall.js",
20101
20100
  "docs:cli": "node scripts/generate-cli-docs.mjs"
20102
20101
  },
@@ -20148,7 +20147,7 @@ var package_default = {
20148
20147
  dotenv: "^17.0.0",
20149
20148
  ethers: "^6.13.4",
20150
20149
  "fs-extra": "^11.3.0",
20151
- "genlayer-js": "^1.0.0",
20150
+ "genlayer-js": "^1.1.8",
20152
20151
  inquirer: "^12.0.0",
20153
20152
  keytar: "^7.9.0",
20154
20153
  "node-fetch": "^3.0.0",
@@ -21585,11 +21584,14 @@ var JsonRpcClient = class {
21585
21584
  params
21586
21585
  })
21587
21586
  });
21588
- if (response.ok) {
21589
- return response.json();
21590
- }
21591
21587
  const result = await response.json();
21592
- throw new Error(result?.error?.message || response.statusText);
21588
+ if (!response.ok) {
21589
+ throw new Error(result?.error?.message || result?.error || response.statusText);
21590
+ }
21591
+ if (result?.error) {
21592
+ throw new Error(result.error.message || String(result.error));
21593
+ }
21594
+ return result;
21593
21595
  }
21594
21596
  };
21595
21597
  var rpcClient = new JsonRpcClient(DEFAULT_JSON_RPC_URL);
@@ -50340,9 +50342,20 @@ function accountActions(client) {
50340
50342
  params: [address, amount]
50341
50343
  });
50342
50344
  },
50345
+ /**
50346
+ * Returns the transaction count (next nonce) for an address.
50347
+ *
50348
+ * Defaults to `"pending"` so that rapid sequential submissions from the
50349
+ * same account receive distinct nonces. Two submissions issued before the
50350
+ * first confirms would otherwise both see the same `"latest"` count and
50351
+ * collide with an "already known" or "replacement underpriced" error.
50352
+ *
50353
+ * Pass `block: "latest"` explicitly for confirmed-only state
50354
+ * (e.g. reconciliation tooling comparing against on-chain finality).
50355
+ */
50343
50356
  getCurrentNonce: async ({
50344
50357
  address,
50345
- block = "latest"
50358
+ block = "pending"
50346
50359
  }) => {
50347
50360
  const addressToUse = address || client.account?.address;
50348
50361
  if (!addressToUse) {
@@ -50708,6 +50721,13 @@ var transactions = transactions_exports;
50708
50721
  function b64ToArray(b64) {
50709
50722
  return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
50710
50723
  }
50724
+ function arrayToB64(bytes) {
50725
+ let binary = "";
50726
+ for (let i2 = 0; i2 < bytes.length; i2++) {
50727
+ binary += String.fromCharCode(bytes[i2]);
50728
+ }
50729
+ return btoa(binary);
50730
+ }
50711
50731
  function calldataToUserFriendlyJson(cd) {
50712
50732
  return {
50713
50733
  raw: Array.from(cd),
@@ -50806,37 +50826,49 @@ function extractGenCallResult(result) {
50806
50826
  }
50807
50827
  var contractActions = (client, publicClient) => {
50808
50828
  return {
50809
- /** Retrieves the source code of a deployed contract. Studio only. */
50829
+ /** Retrieves the source code of a deployed contract. */
50810
50830
  getContractCode: async (address) => {
50811
- if (!client.chain.isStudio) {
50812
- throw new Error(`getContractCode is only available on Studio networks (current chain: ${client.chain.name})`);
50813
- }
50831
+ const params = client.chain.isStudio ? [address] : [{ address }];
50814
50832
  const result = await client.request({
50815
50833
  method: "gen_getContractCode",
50816
- params: [address]
50834
+ params
50817
50835
  });
50818
50836
  const codeBytes = b64ToArray(result);
50819
50837
  return new TextDecoder().decode(codeBytes);
50820
50838
  },
50821
- /** Gets the schema (methods and constructor) of a deployed contract. Studio only. */
50839
+ /** Gets the schema (methods and constructor) of a deployed contract. */
50822
50840
  getContractSchema: async (address) => {
50823
- if (!client.chain.isStudio) {
50824
- throw new Error(`getContractSchema is only available on Studio networks (current chain: ${client.chain.name})`);
50841
+ if (client.chain.isStudio) {
50842
+ const schema2 = await client.request({
50843
+ method: "gen_getContractSchema",
50844
+ params: [address]
50845
+ });
50846
+ return schema2;
50825
50847
  }
50848
+ const codeB64 = await client.request({
50849
+ method: "gen_getContractCode",
50850
+ params: [{ address }]
50851
+ });
50826
50852
  const schema = await client.request({
50827
50853
  method: "gen_getContractSchema",
50828
- params: [address]
50854
+ params: [{ code: codeB64 }]
50829
50855
  });
50830
50856
  return schema;
50831
50857
  },
50832
- /** Generates a schema for contract code without deploying it. Studio only. */
50858
+ /** Generates a schema for contract code without deploying it. */
50833
50859
  getContractSchemaForCode: async (contractCode) => {
50834
- if (!client.chain.isStudio) {
50835
- throw new Error(`getContractSchemaForCode is only available on Studio networks (current chain: ${client.chain.name})`);
50860
+ if (client.chain.isStudio) {
50861
+ const schema2 = await client.request({
50862
+ method: "gen_getContractSchemaForCode",
50863
+ params: [toHex(contractCode)]
50864
+ });
50865
+ return schema2;
50836
50866
  }
50867
+ const bytes = typeof contractCode === "string" ? new TextEncoder().encode(contractCode) : contractCode;
50868
+ const codeB64 = arrayToB64(bytes);
50837
50869
  const schema = await client.request({
50838
- method: "gen_getContractSchemaForCode",
50839
- params: [toHex(contractCode)]
50870
+ method: "gen_getContractSchema",
50871
+ params: [{ code: codeB64 }]
50840
50872
  });
50841
50873
  return schema;
50842
50874
  },
@@ -51202,10 +51234,11 @@ var _encodeAddTransactionData = ({
51202
51234
  functionName: "addTransaction",
51203
51235
  args: addTransactionArgs
51204
51236
  });
51237
+ const validUntil = BigInt(Math.floor(Date.now() / 1e3) + 3600);
51205
51238
  const encodedDataV6 = encodeFunctionData({
51206
51239
  abi: ADD_TRANSACTION_ABI_V6,
51207
51240
  functionName: "addTransaction",
51208
- args: [...addTransactionArgs, 0n]
51241
+ args: [...addTransactionArgs, validUntil]
51209
51242
  });
51210
51243
  if (getAddTransactionInputCount(client.chain.consensusMainContract?.abi) >= 6) {
51211
51244
  return {
@@ -53522,9 +53555,7 @@ async function checkCommand(command, toolName) {
53522
53555
  try {
53523
53556
  await util.promisify(exec)(command);
53524
53557
  } catch (error) {
53525
- if (error.stderr) {
53526
- throw new MissingRequirementError(toolName);
53527
- }
53558
+ throw new MissingRequirementError(toolName);
53528
53559
  }
53529
53560
  }
53530
53561
  async function executeCommand(cmdsByPlatform, toolName) {
@@ -53547,23 +53578,25 @@ function openUrl(url) {
53547
53578
  return open_default(url);
53548
53579
  }
53549
53580
  async function getVersion2(toolName) {
53581
+ let toolResponse;
53550
53582
  try {
53551
- const toolResponse = await util.promisify(exec)(`${toolName} --version`);
53552
- if (toolResponse.stderr) {
53553
- throw new Error(toolResponse.stderr);
53554
- }
53555
- try {
53556
- const versionMatch = toolResponse.stdout.match(/(\d+\.\d+\.\d+)/);
53557
- if (versionMatch) {
53558
- return versionMatch[1];
53559
- }
53560
- } catch (err) {
53561
- throw new Error(`Could not parse ${toolName} version.`);
53562
- }
53583
+ toolResponse = await util.promisify(exec)(`${toolName} --version`);
53563
53584
  } catch (error) {
53564
53585
  throw new Error(`Error getting ${toolName} version.`);
53565
53586
  }
53566
- return "";
53587
+ if (toolResponse.stderr) {
53588
+ throw new Error(`Error getting ${toolName} version.`);
53589
+ }
53590
+ if (toolResponse.stdout == null) {
53591
+ throw new Error(`Error getting ${toolName} version.`);
53592
+ }
53593
+ const versionMatch = toolResponse.stdout.match(/(\d+\.\d+\.\d+)/);
53594
+ if (versionMatch) {
53595
+ return versionMatch[1];
53596
+ }
53597
+ throw new Error(
53598
+ `Could not parse ${toolName} version from output: "${toolResponse.stdout}". Expected format: X.Y.Z`
53599
+ );
53567
53600
  }
53568
53601
 
53569
53602
  // src/lib/errors/versionRequired.ts
@@ -54680,6 +54713,200 @@ import fs9 from "fs";
54680
54713
  import path5 from "path";
54681
54714
  import { pathToFileURL } from "url";
54682
54715
  import { buildSync } from "esbuild";
54716
+
54717
+ // src/commands/contracts/fees.ts
54718
+ var parseJsonObject = (value, optionName) => {
54719
+ let parsed;
54720
+ try {
54721
+ parsed = JSON.parse(value);
54722
+ } catch (error) {
54723
+ throw new Error(`${optionName} must be valid JSON.`);
54724
+ }
54725
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
54726
+ throw new Error(`${optionName} must be a JSON object.`);
54727
+ }
54728
+ assertSafeJsonNumbers(parsed, optionName);
54729
+ return parsed;
54730
+ };
54731
+ var assertSafeJsonNumbers = (value, path8) => {
54732
+ if (typeof value === "number" && !Number.isSafeInteger(value)) {
54733
+ throw new Error(`${path8} contains an unsafe number. Quote large integer values as strings.`);
54734
+ }
54735
+ if (Array.isArray(value)) {
54736
+ value.forEach((item, index2) => assertSafeJsonNumbers(item, `${path8}[${index2}]`));
54737
+ return;
54738
+ }
54739
+ if (value && typeof value === "object") {
54740
+ for (const [key, item] of Object.entries(value)) {
54741
+ assertSafeJsonNumbers(item, `${path8}.${key}`);
54742
+ }
54743
+ }
54744
+ };
54745
+ var parseBigNumberishOption = (value, optionName) => {
54746
+ if (value === void 0) return void 0;
54747
+ const trimmed = value.trim();
54748
+ if (!/^(0x[0-9a-fA-F]+|[0-9]+)$/.test(trimmed)) {
54749
+ throw new Error(`${optionName} must be a non-negative integer.`);
54750
+ }
54751
+ return trimmed;
54752
+ };
54753
+ var CALL_KEY_UNNAMED = "0x0000000000000000000000000000000000000000000000000000000000000000";
54754
+ var bytesToPaddedCallKey = (bytes) => {
54755
+ if (bytes.length > 32) {
54756
+ throw new Error("call key source bytes must be 32 bytes or fewer.");
54757
+ }
54758
+ return `0x${toHex(bytes).slice(2).padEnd(64, "0")}`;
54759
+ };
54760
+ var deriveInternalMessageCallKey = (methodName = "") => {
54761
+ const methodBytes = new TextEncoder().encode(methodName);
54762
+ if (methodBytes.length < 32) {
54763
+ return bytesToPaddedCallKey(methodBytes);
54764
+ }
54765
+ const hashed = keccak256(methodBytes);
54766
+ const lastByte = Number.parseInt(hashed.slice(-2), 16) | 1;
54767
+ return `${hashed.slice(0, -2)}${lastByte.toString(16).padStart(2, "0")}`;
54768
+ };
54769
+ var deriveExternalMessageCallKey = (selectorOrCalldata) => {
54770
+ const bytes = hexToBytes(selectorOrCalldata);
54771
+ if (bytes.length < 4) {
54772
+ return CALL_KEY_UNNAMED;
54773
+ }
54774
+ return bytesToPaddedCallKey(bytes.slice(0, 4));
54775
+ };
54776
+ var normalizeMessageType = (messageType, index2) => {
54777
+ if (messageType === void 0) {
54778
+ return void 0;
54779
+ }
54780
+ if (typeof messageType === "number") {
54781
+ if (messageType === 0 || messageType === 1) {
54782
+ return messageType;
54783
+ }
54784
+ throw new Error(`--fees.messageAllocations[${index2}].messageType must be "internal", "external", 0, or 1.`);
54785
+ }
54786
+ if (typeof messageType !== "string") {
54787
+ return void 0;
54788
+ }
54789
+ const normalized = messageType.toLowerCase();
54790
+ if (normalized === "internal") {
54791
+ return 1;
54792
+ }
54793
+ if (normalized === "external") {
54794
+ return 0;
54795
+ }
54796
+ throw new Error(`--fees.messageAllocations[${index2}].messageType must be "internal" or "external".`);
54797
+ };
54798
+ var readStringField = (allocation, field, index2) => {
54799
+ const value = allocation[field];
54800
+ if (typeof value !== "string") {
54801
+ throw new Error(`--fees.messageAllocations[${index2}].${field} must be a string.`);
54802
+ }
54803
+ return value;
54804
+ };
54805
+ var assertFourByteSelector = (selector, field, index2) => {
54806
+ if (!/^0x[0-9a-fA-F]{8}$/.test(selector)) {
54807
+ throw new Error(`--fees.messageAllocations[${index2}].${field} must be a 4-byte hex selector.`);
54808
+ }
54809
+ };
54810
+ var assertHexBytes = (hex, field, index2) => {
54811
+ if (!/^0x([0-9a-fA-F]{2})*$/.test(hex)) {
54812
+ throw new Error(`--fees.messageAllocations[${index2}].${field} must be even-length hex bytes.`);
54813
+ }
54814
+ };
54815
+ var normalizeMessageAllocationCallKey = (allocation, messageType, index2) => {
54816
+ const helperFields = [
54817
+ "callKeyMethod",
54818
+ "callKeySelector",
54819
+ "callKeyCalldata",
54820
+ "functionSelector"
54821
+ ].filter((field) => allocation[field] !== void 0);
54822
+ if (allocation.callKey !== void 0 && helperFields.length > 0) {
54823
+ throw new Error(`--fees.messageAllocations[${index2}] cannot combine callKey with call-key helper fields.`);
54824
+ }
54825
+ if (helperFields.length > 1) {
54826
+ throw new Error(`--fees.messageAllocations[${index2}] must use only one call-key helper field.`);
54827
+ }
54828
+ const {
54829
+ callKeyMethod,
54830
+ callKeySelector,
54831
+ callKeyCalldata,
54832
+ functionSelector,
54833
+ ...normalized
54834
+ } = allocation;
54835
+ if (helperFields.length === 0) {
54836
+ return normalized;
54837
+ }
54838
+ const helperField = helperFields[0];
54839
+ if (helperField === "callKeyMethod") {
54840
+ if (messageType === 0) {
54841
+ throw new Error(`--fees.messageAllocations[${index2}].callKeyMethod requires an internal message allocation.`);
54842
+ }
54843
+ normalized.messageType = messageType ?? 1;
54844
+ normalized.callKey = deriveInternalMessageCallKey(readStringField(allocation, helperField, index2));
54845
+ return normalized;
54846
+ }
54847
+ if (messageType === 1) {
54848
+ throw new Error(`--fees.messageAllocations[${index2}].${helperField} requires an external message allocation.`);
54849
+ }
54850
+ const selectorOrCalldata = readStringField(allocation, helperField, index2);
54851
+ if (helperField === "callKeySelector" || helperField === "functionSelector") {
54852
+ assertFourByteSelector(selectorOrCalldata, helperField, index2);
54853
+ } else {
54854
+ assertHexBytes(selectorOrCalldata, helperField, index2);
54855
+ }
54856
+ normalized.messageType = messageType ?? 0;
54857
+ normalized.callKey = deriveExternalMessageCallKey(selectorOrCalldata);
54858
+ return normalized;
54859
+ };
54860
+ var normalizeMessageTypes = (fees) => {
54861
+ if (!Array.isArray(fees.messageAllocations)) {
54862
+ return fees;
54863
+ }
54864
+ return {
54865
+ ...fees,
54866
+ messageAllocations: fees.messageAllocations.map((allocation, index2) => {
54867
+ if (!allocation || typeof allocation !== "object" || Array.isArray(allocation)) {
54868
+ throw new Error(`--fees.messageAllocations[${index2}] must be an object.`);
54869
+ }
54870
+ const messageType = normalizeMessageType(allocation.messageType, index2);
54871
+ return normalizeMessageAllocationCallKey({
54872
+ ...allocation,
54873
+ ...messageType === void 0 ? {} : { messageType }
54874
+ }, messageType, index2);
54875
+ })
54876
+ };
54877
+ };
54878
+ var parseTransactionFees = (options) => {
54879
+ const feeValue = parseBigNumberishOption(options.feeValue, "--fee-value");
54880
+ let fees = options.fees ? parseJsonObject(options.fees, "--fees") : void 0;
54881
+ if (!fees && feeValue === void 0) {
54882
+ return void 0;
54883
+ }
54884
+ fees = normalizeMessageTypes(fees ?? {});
54885
+ if (feeValue !== void 0) {
54886
+ fees.feeValue = feeValue;
54887
+ }
54888
+ return fees;
54889
+ };
54890
+ var parseFeeEstimateOptions = (options) => {
54891
+ if (!options.fees) {
54892
+ return void 0;
54893
+ }
54894
+ const parsed = normalizeMessageTypes(parseJsonObject(options.fees, "--fees"));
54895
+ if (parsed.distribution && typeof parsed.distribution === "object" && !Array.isArray(parsed.distribution)) {
54896
+ const { distribution, messageAllocations, ...rest } = parsed;
54897
+ return {
54898
+ ...distribution,
54899
+ ...messageAllocations !== void 0 ? { messageAllocations } : {},
54900
+ ...rest
54901
+ };
54902
+ }
54903
+ return parsed;
54904
+ };
54905
+ var parseValidUntil = (options) => {
54906
+ return parseBigNumberishOption(options.validUntil, "--valid-until");
54907
+ };
54908
+
54909
+ // src/commands/contracts/deploy.ts
54683
54910
  var DeployAction = class extends BaseAction {
54684
54911
  constructor() {
54685
54912
  super();
@@ -54776,6 +55003,10 @@ var DeployAction = class extends BaseAction {
54776
55003
  }
54777
55004
  const leaderOnly = false;
54778
55005
  const deployParams = { code: contractCode, args: options.args, leaderOnly };
55006
+ const fees = parseTransactionFees(options);
55007
+ const validUntil = parseValidUntil(options);
55008
+ if (fees) deployParams.fees = fees;
55009
+ if (validUntil !== void 0) deployParams.validUntil = validUntil;
54779
55010
  this.setSpinnerText("Starting contract deployment...");
54780
55011
  this.log("Deployment Parameters:", deployParams);
54781
55012
  const hash3 = await client.deployContract(deployParams);
@@ -54835,18 +55066,26 @@ var WriteAction = class extends BaseAction {
54835
55066
  contractAddress,
54836
55067
  method,
54837
55068
  args,
54838
- rpc
55069
+ rpc,
55070
+ fees,
55071
+ feeValue,
55072
+ validUntil
54839
55073
  }) {
54840
55074
  const client = await this.getClient(rpc);
54841
55075
  await client.initializeConsensusSmartContract();
54842
55076
  this.startSpinner(`Calling write method ${method} on contract at ${contractAddress}...`);
54843
55077
  try {
54844
- const hash3 = await client.writeContract({
55078
+ const writeParams = {
54845
55079
  address: contractAddress,
54846
55080
  functionName: method,
54847
55081
  args,
54848
55082
  value: 0n
54849
- });
55083
+ };
55084
+ const parsedFees = parseTransactionFees({ fees, feeValue, validUntil });
55085
+ const parsedValidUntil = parseValidUntil({ fees, feeValue, validUntil });
55086
+ if (parsedFees) writeParams.fees = parsedFees;
55087
+ if (parsedValidUntil !== void 0) writeParams.validUntil = parsedValidUntil;
55088
+ const hash3 = await client.writeContract(writeParams);
54850
55089
  this.log("Write Transaction Hash:", hash3);
54851
55090
  const result = await client.waitForTransactionReceipt({
54852
55091
  hash: hash3,
@@ -54902,6 +55141,111 @@ var CodeAction = class extends BaseAction {
54902
55141
  }
54903
55142
  };
54904
55143
 
55144
+ // src/commands/contracts/estimateFees.ts
55145
+ var toTransactionFees = (estimate) => ({
55146
+ distribution: estimate.distribution,
55147
+ ...estimate.messageAllocations ? { messageAllocations: estimate.messageAllocations } : {},
55148
+ feeValue: estimate.feeValue ?? estimate.fee_value
55149
+ });
55150
+ var toJsonSafe = (value) => {
55151
+ if (typeof value === "bigint") return value.toString();
55152
+ if (Array.isArray(value)) return value.map(toJsonSafe);
55153
+ if (value && typeof value === "object") {
55154
+ return Object.fromEntries(
55155
+ Object.entries(value).filter(([, item]) => item !== void 0).map(([key, item]) => [key, toJsonSafe(item)])
55156
+ );
55157
+ }
55158
+ return value;
55159
+ };
55160
+ var simulationFeeReport = (simulation) => simulation.feeReport ?? simulation.feeAccounting?.execution_fee_report;
55161
+ var withSimulationReport = (estimate, simulation) => {
55162
+ if (!simulation || typeof simulation !== "object" || Array.isArray(simulation)) {
55163
+ return estimate;
55164
+ }
55165
+ const simulationRecord = simulation;
55166
+ return {
55167
+ ...estimate && typeof estimate === "object" && !Array.isArray(estimate) ? estimate : { estimate },
55168
+ simulation: {
55169
+ feeAccounting: simulationRecord.feeAccounting,
55170
+ feeReport: simulationFeeReport(simulationRecord)
55171
+ }
55172
+ };
55173
+ };
55174
+ var EstimateFeesAction = class extends BaseAction {
55175
+ constructor() {
55176
+ super();
55177
+ }
55178
+ async estimate({
55179
+ contractAddress,
55180
+ method,
55181
+ args,
55182
+ rpc,
55183
+ fees,
55184
+ json,
55185
+ includeReport
55186
+ }) {
55187
+ try {
55188
+ const client = await this.getClient(rpc, true);
55189
+ await client.initializeConsensusSmartContract();
55190
+ const estimateOptions = parseFeeEstimateOptions({ fees });
55191
+ if (!json) this.startSpinner("Estimating transaction fees...");
55192
+ let estimate;
55193
+ if (contractAddress || method) {
55194
+ if (!contractAddress || !method) {
55195
+ this.failSpinner("Both contractAddress and method are required for simulation-derived fee estimates.");
55196
+ return;
55197
+ }
55198
+ if (!json) this.setSpinnerText(`Simulating ${method} on ${contractAddress}...`);
55199
+ if (!includeReport && typeof client.estimateTransactionFeesForWrite === "function") {
55200
+ estimate = await client.estimateTransactionFeesForWrite({
55201
+ ...estimateOptions ?? {},
55202
+ address: contractAddress,
55203
+ functionName: method,
55204
+ args: args ?? []
55205
+ });
55206
+ } else {
55207
+ if (typeof client.simulateWriteContract !== "function") {
55208
+ this.failSpinner("The active genlayer-js client does not support write simulation.");
55209
+ return;
55210
+ }
55211
+ if (typeof client.estimateTransactionFeesFromSimulation !== "function") {
55212
+ this.failSpinner("The active genlayer-js client does not support simulation-derived fee estimates.");
55213
+ return;
55214
+ }
55215
+ const initialEstimate = await client.estimateTransactionFees(estimateOptions);
55216
+ const simulation = await client.simulateWriteContract({
55217
+ address: contractAddress,
55218
+ functionName: method,
55219
+ args: args ?? [],
55220
+ includeReceipt: true,
55221
+ fees: toTransactionFees(initialEstimate)
55222
+ });
55223
+ estimate = await client.estimateTransactionFeesFromSimulation({
55224
+ ...estimateOptions ?? {},
55225
+ simulation
55226
+ });
55227
+ if (includeReport) {
55228
+ estimate = withSimulationReport(estimate, simulation);
55229
+ }
55230
+ }
55231
+ } else {
55232
+ if (includeReport) {
55233
+ this.failSpinner("--include-report requires both contractAddress and method.");
55234
+ return;
55235
+ }
55236
+ estimate = await client.estimateTransactionFees(estimateOptions);
55237
+ }
55238
+ if (json) {
55239
+ console.log(JSON.stringify(toJsonSafe(estimate)));
55240
+ } else {
55241
+ this.succeedSpinner("Fee estimate generated", toJsonSafe(estimate));
55242
+ }
55243
+ } catch (error) {
55244
+ this.failSpinner("Error estimating transaction fees", error);
55245
+ }
55246
+ }
55247
+ };
55248
+
54905
55249
  // src/commands/contracts/index.ts
54906
55250
  var ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
54907
55251
  var ADDR_PREFIX_RE = /^addr#([0-9a-fA-F]{40})$/;
@@ -54967,8 +55311,24 @@ var ARGS_HELP = [
54967
55311
  ` array: '[1, 2, "three"]'`,
54968
55312
  ` dict: '{"key": "value"}'`
54969
55313
  ].join("\n");
55314
+ var FEES_HELP = [
55315
+ "Transaction fee options JSON passed to genlayer-js.",
55316
+ "Example:",
55317
+ ` '{"distribution":{"leaderTimeunitsAllocation":"100","validatorTimeunitsAllocation":"200","rotations":["0"]}}'`,
55318
+ "Omit --fee-value to let genlayer-js derive the fee deposit from FeeManager or Studio.",
55319
+ 'Message allocation messageType may be "internal", "external", 0, or 1.',
55320
+ "Use callKeyMethod for internal messages, or callKeySelector/callKeyCalldata for external messages."
55321
+ ].join("\n");
55322
+ var FEE_ESTIMATE_HELP = [
55323
+ "Fee estimate options JSON passed to genlayer-js estimateTransactionFees.",
55324
+ "You may pass either flat estimate options or a transaction fee object with distribution/messageAllocations.",
55325
+ "Example:",
55326
+ ` '{"distribution":{"leaderTimeunitsAllocation":"100","validatorTimeunitsAllocation":"200","rotations":["0"]}}'`,
55327
+ 'Message allocation messageType may be "internal", "external", 0, or 1.',
55328
+ "Use callKeyMethod for internal messages, or callKeySelector/callKeyCalldata for external messages."
55329
+ ].join("\n");
54970
55330
  function initializeContractsCommands(program2) {
54971
- program2.command("deploy").description("Deploy intelligent contracts").option("--contract <contractPath>", "Path to the smart contract to deploy").option("--rpc <rpcUrl>", "RPC URL for the network").option("--args <args...>", ARGS_HELP, parseArg, []).action(async (options) => {
55331
+ program2.command("deploy").description("Deploy intelligent contracts").option("--contract <contractPath>", "Path to the smart contract to deploy").option("--rpc <rpcUrl>", "RPC URL for the network").option("--fees <json>", FEES_HELP).option("--fee-value <wei>", "Fee deposit value to send with the transaction").option("--valid-until <unixTimestamp>", "Unix timestamp after which the transaction is invalid").option("--args <args...>", ARGS_HELP, parseArg, []).action(async (options) => {
54972
55332
  const deployer = new DeployAction();
54973
55333
  if (options.contract) {
54974
55334
  await deployer.deploy(options);
@@ -54986,7 +55346,7 @@ function initializeContractsCommands(program2) {
54986
55346
  const callAction = new CallAction();
54987
55347
  await callAction.call({ contractAddress, method, ...options });
54988
55348
  });
54989
- program2.command("write <contractAddress> <method>").description("Sends a transaction to a contract method that modifies the state").option("--rpc <rpcUrl>", "RPC URL for the network").option(
55349
+ program2.command("write <contractAddress> <method>").description("Sends a transaction to a contract method that modifies the state").option("--rpc <rpcUrl>", "RPC URL for the network").option("--fees <json>", FEES_HELP).option("--fee-value <wei>", "Fee deposit value to send with the transaction").option("--valid-until <unixTimestamp>", "Unix timestamp after which the transaction is invalid").option(
54990
55350
  "--args <args...>",
54991
55351
  ARGS_HELP,
54992
55352
  parseArg,
@@ -54995,6 +55355,15 @@ function initializeContractsCommands(program2) {
54995
55355
  const writeAction = new WriteAction();
54996
55356
  await writeAction.write({ contractAddress, method, ...options });
54997
55357
  });
55358
+ program2.command("estimate-fees [contractAddress] [method]").description("Build a transaction fee preset, optionally from a Studio/localnet write simulation").option("--rpc <rpcUrl>", "RPC URL for the network").option("--fees <json>", FEE_ESTIMATE_HELP).option("--json", "Print the fee estimate as JSON without spinner output").option("--include-report", "Include simulation fee accounting/report in the generated estimate output").option(
55359
+ "--args <args...>",
55360
+ ARGS_HELP,
55361
+ parseArg,
55362
+ []
55363
+ ).action(async (contractAddress, method, options) => {
55364
+ const estimateFeesAction = new EstimateFeesAction();
55365
+ await estimateFeesAction.estimate({ contractAddress, method, ...options });
55366
+ });
54998
55367
  program2.command("schema <contractAddress>").description("Get the schema for a deployed contract").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (contractAddress, options) => {
54999
55368
  const schemaAction = new SchemaAction();
55000
55369
  await schemaAction.schema({ contractAddress, ...options });
@@ -55112,6 +55481,7 @@ var ValidatorsAction = class extends BaseAction {
55112
55481
  method: "sim_countValidators",
55113
55482
  params: []
55114
55483
  });
55484
+ console.log(`Total Validators: ${result.result}`);
55115
55485
  this.succeedSpinner(`Total Validators: ${result.result}`);
55116
55486
  } catch (error) {
55117
55487
  this.failSpinner("Error counting validators", error);
@@ -55125,13 +55495,13 @@ var ValidatorsAction = class extends BaseAction {
55125
55495
  params: [options.address]
55126
55496
  });
55127
55497
  this.log("Current Validator Details:", currentValidator.result);
55128
- const parsedStake = options.stake ? parseInt(options.stake, 10) : currentValidator.result.stake;
55129
- if (isNaN(parsedStake) || parsedStake < 0) {
55498
+ const parsedStake = options.stake ? parseInt(options.stake, 10) : Number(currentValidator.result.stake);
55499
+ if (!Number.isInteger(parsedStake) || parsedStake < 0) {
55130
55500
  return this.failSpinner("Invalid stake value. Stake must be a positive integer.");
55131
55501
  }
55132
55502
  const updatedValidator = {
55133
55503
  address: options.address,
55134
- stake: options.stake || currentValidator.result.stake,
55504
+ stake: parsedStake,
55135
55505
  provider: options.provider || currentValidator.result.provider,
55136
55506
  model: options.model || currentValidator.result.model,
55137
55507
  config: options.config ? JSON.parse(options.config) : currentValidator.result.config
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genlayer",
3
- "version": "0.39.0",
3
+ "version": "0.39.2",
4
4
  "description": "GenLayer Command Line Tool",
5
5
  "main": "src/index.ts",
6
6
  "type": "module",
@@ -14,8 +14,7 @@
14
14
  "test:smoke": "vitest run --config vitest.smoke.config.ts",
15
15
  "dev": "cross-env NODE_ENV=development node esbuild.config.js",
16
16
  "build": "cross-env NODE_ENV=production node esbuild.config.js",
17
- "release": "release-it --ci",
18
- "release-beta": "release-it --ci --preRelease=beta",
17
+ "release": "./scripts/release.sh",
19
18
  "postinstall": "node ./scripts/postinstall.js",
20
19
  "docs:cli": "node scripts/generate-cli-docs.mjs"
21
20
  },
@@ -67,7 +66,7 @@
67
66
  "dotenv": "^17.0.0",
68
67
  "ethers": "^6.13.4",
69
68
  "fs-extra": "^11.3.0",
70
- "genlayer-js": "^1.0.0",
69
+ "genlayer-js": "^1.1.8",
71
70
  "inquirer": "^12.0.0",
72
71
  "keytar": "^7.9.0",
73
72
  "node-fetch": "^3.0.0",