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/.claude/skills/release/SKILL.md +89 -0
- package/.github/e2e-track +1 -0
- package/.github/workflows/e2e-housekeeper.yml +84 -0
- package/.github/workflows/e2e.yml +740 -0
- package/.github/workflows/publish.yml +43 -29
- package/.github/workflows/{cli-docs.yml → sync-docs.yml} +3 -20
- package/.github/workflows/validate-code.yml +1 -1
- package/CHANGELOG.md +19 -0
- package/CONTRIBUTING.md +24 -0
- package/README.md +50 -1
- package/dist/index.js +418 -48
- package/package.json +3 -4
- package/scripts/release.sh +157 -0
- package/src/commands/contracts/deploy.ts +6 -1
- package/src/commands/contracts/estimateFees.ts +133 -0
- package/src/commands/contracts/fees.ts +236 -0
- package/src/commands/contracts/index.ts +43 -0
- package/src/commands/contracts/write.ts +16 -3
- package/src/commands/localnet/validators.ts +4 -5
- package/src/lib/clients/jsonRpcClient.ts +9 -4
- package/src/lib/clients/system.ts +19 -17
- package/tests/actions/deploy.test.ts +49 -0
- package/tests/actions/estimateFees.test.ts +271 -0
- package/tests/actions/validators.test.ts +5 -5
- package/tests/actions/write.test.ts +47 -0
- package/tests/commands/deploy.test.ts +25 -0
- package/tests/commands/estimateFees.test.ts +98 -0
- package/tests/commands/write.test.ts +26 -0
- package/tests/libs/jsonRpcClient.test.ts +18 -0
- package/tests/libs/system.test.ts +36 -3
- package/tsconfig.json +2 -3
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.
|
|
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
|
|
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.
|
|
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
|
-
|
|
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 = "
|
|
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.
|
|
50829
|
+
/** Retrieves the source code of a deployed contract. */
|
|
50810
50830
|
getContractCode: async (address) => {
|
|
50811
|
-
|
|
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
|
|
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.
|
|
50839
|
+
/** Gets the schema (methods and constructor) of a deployed contract. */
|
|
50822
50840
|
getContractSchema: async (address) => {
|
|
50823
|
-
if (
|
|
50824
|
-
|
|
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: [
|
|
50854
|
+
params: [{ code: codeB64 }]
|
|
50829
50855
|
});
|
|
50830
50856
|
return schema;
|
|
50831
50857
|
},
|
|
50832
|
-
/** Generates a schema for contract code without deploying it.
|
|
50858
|
+
/** Generates a schema for contract code without deploying it. */
|
|
50833
50859
|
getContractSchemaForCode: async (contractCode) => {
|
|
50834
|
-
if (
|
|
50835
|
-
|
|
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: "
|
|
50839
|
-
params: [
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 (
|
|
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:
|
|
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.
|
|
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
|
|
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.
|
|
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",
|