@suzaku-network/suzaku-cli 1.0.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.
Files changed (194) hide show
  1. package/LICENSE +96 -0
  2. package/README.md +1080 -0
  3. package/bin/cli.js +3 -0
  4. package/defaults/.env.anvil +4 -0
  5. package/defaults/.env.dexalot +7 -0
  6. package/defaults/.env.fuji +4 -0
  7. package/defaults/.env.kiteai +2 -0
  8. package/defaults/.env.mainnet +4 -0
  9. package/defaults/.env.template +10 -0
  10. package/dist/abis/AccessControl.d.ts +176 -0
  11. package/dist/abis/AccessControl.js +230 -0
  12. package/dist/abis/AccessControl.js.map +1 -0
  13. package/dist/abis/BalancerValidatorManager.d.ts +1121 -0
  14. package/dist/abis/BalancerValidatorManager.js +1469 -0
  15. package/dist/abis/BalancerValidatorManager.js.map +1 -0
  16. package/dist/abis/DefaultCollateral.d.ts +620 -0
  17. package/dist/abis/DefaultCollateral.js +811 -0
  18. package/dist/abis/DefaultCollateral.js.map +1 -0
  19. package/dist/abis/ERC20.d.ts +635 -0
  20. package/dist/abis/ERC20.js +831 -0
  21. package/dist/abis/ERC20.js.map +1 -0
  22. package/dist/abis/IWarpMessenger.d.ts +104 -0
  23. package/dist/abis/IWarpMessenger.js +139 -0
  24. package/dist/abis/IWarpMessenger.js.map +1 -0
  25. package/dist/abis/KiteStakingManager.d.ts +1459 -0
  26. package/dist/abis/KiteStakingManager.js +1886 -0
  27. package/dist/abis/KiteStakingManager.js.map +1 -0
  28. package/dist/abis/L1Middleware.d.ts +1712 -0
  29. package/dist/abis/L1Middleware.js +2242 -0
  30. package/dist/abis/L1Middleware.js.map +1 -0
  31. package/dist/abis/L1Registry.d.ts +415 -0
  32. package/dist/abis/L1Registry.js +544 -0
  33. package/dist/abis/L1Registry.js.map +1 -0
  34. package/dist/abis/L1RestakeDelegator.d.ts +865 -0
  35. package/dist/abis/L1RestakeDelegator.js +1118 -0
  36. package/dist/abis/L1RestakeDelegator.js.map +1 -0
  37. package/dist/abis/OperatorL1OptInService.d.ts +288 -0
  38. package/dist/abis/OperatorL1OptInService.js +374 -0
  39. package/dist/abis/OperatorL1OptInService.js.map +1 -0
  40. package/dist/abis/OperatorRegistry.d.ts +125 -0
  41. package/dist/abis/OperatorRegistry.js +166 -0
  42. package/dist/abis/OperatorRegistry.js.map +1 -0
  43. package/dist/abis/OperatorVaultOptInService.d.ts +288 -0
  44. package/dist/abis/OperatorVaultOptInService.js +374 -0
  45. package/dist/abis/OperatorVaultOptInService.js.map +1 -0
  46. package/dist/abis/Ownable.d.ts +59 -0
  47. package/dist/abis/Ownable.js +79 -0
  48. package/dist/abis/Ownable.js.map +1 -0
  49. package/dist/abis/PoASecurityModule.d.ts +225 -0
  50. package/dist/abis/PoASecurityModule.js +299 -0
  51. package/dist/abis/PoASecurityModule.js.map +1 -0
  52. package/dist/abis/RewardsNativeToken.d.ts +1334 -0
  53. package/dist/abis/RewardsNativeToken.js +1749 -0
  54. package/dist/abis/RewardsNativeToken.js.map +1 -0
  55. package/dist/abis/StakingVault.d.ts +2913 -0
  56. package/dist/abis/StakingVault.js +3780 -0
  57. package/dist/abis/StakingVault.js.map +1 -0
  58. package/dist/abis/StakingVaultOperations.d.ts +980 -0
  59. package/dist/abis/StakingVaultOperations.js +1270 -0
  60. package/dist/abis/StakingVaultOperations.js.map +1 -0
  61. package/dist/abis/UptimeTracker.d.ts +300 -0
  62. package/dist/abis/UptimeTracker.js +397 -0
  63. package/dist/abis/UptimeTracker.js.map +1 -0
  64. package/dist/abis/ValidatorManager.d.ts +842 -0
  65. package/dist/abis/ValidatorManager.js +1101 -0
  66. package/dist/abis/ValidatorManager.js.map +1 -0
  67. package/dist/abis/VaultFactory.d.ts +288 -0
  68. package/dist/abis/VaultFactory.js +378 -0
  69. package/dist/abis/VaultFactory.js.map +1 -0
  70. package/dist/abis/VaultManager.d.ts +519 -0
  71. package/dist/abis/VaultManager.js +678 -0
  72. package/dist/abis/VaultManager.js.map +1 -0
  73. package/dist/abis/VaultTokenized.d.ts +1626 -0
  74. package/dist/abis/VaultTokenized.js +2114 -0
  75. package/dist/abis/VaultTokenized.js.map +1 -0
  76. package/dist/abis/abi-selectors.json +700 -0
  77. package/dist/abis/index.d.ts +18356 -0
  78. package/dist/abis/index.js +58 -0
  79. package/dist/abis/index.js.map +1 -0
  80. package/dist/accessControl.d.ts +15 -0
  81. package/dist/accessControl.js +36 -0
  82. package/dist/accessControl.js.map +1 -0
  83. package/dist/balancer.d.ts +25 -0
  84. package/dist/balancer.js +42 -0
  85. package/dist/balancer.js.map +1 -0
  86. package/dist/cli.d.mts +1 -0
  87. package/dist/cli.d.ts +2 -0
  88. package/dist/cli.js +3183 -0
  89. package/dist/cli.js.map +1 -0
  90. package/dist/cli.mjs +31343 -0
  91. package/dist/cli.mjs.map +1 -0
  92. package/dist/client.d.ts +34 -0
  93. package/dist/client.js +76 -0
  94. package/dist/client.js.map +1 -0
  95. package/dist/config.d.ts +10 -0
  96. package/dist/config.js +63 -0
  97. package/dist/config.js.map +1 -0
  98. package/dist/delegator.d.ts +4 -0
  99. package/dist/delegator.js +16 -0
  100. package/dist/delegator.js.map +1 -0
  101. package/dist/index.d.mts +19770 -0
  102. package/dist/index.d.ts +7 -0
  103. package/dist/index.js +24 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/index.mjs +27451 -0
  106. package/dist/index.mjs.map +1 -0
  107. package/dist/keyStore.d.ts +3 -0
  108. package/dist/keyStore.js +105 -0
  109. package/dist/keyStore.js.map +1 -0
  110. package/dist/kiteStaking.d.ts +91 -0
  111. package/dist/kiteStaking.js +731 -0
  112. package/dist/kiteStaking.js.map +1 -0
  113. package/dist/l1.d.ts +5 -0
  114. package/dist/l1.js +22 -0
  115. package/dist/l1.js.map +1 -0
  116. package/dist/lib/autoCompletion.d.ts +3 -0
  117. package/dist/lib/autoCompletion.js +55 -0
  118. package/dist/lib/autoCompletion.js.map +1 -0
  119. package/dist/lib/cChainUtils.d.ts +42 -0
  120. package/dist/lib/cChainUtils.js +271 -0
  121. package/dist/lib/cChainUtils.js.map +1 -0
  122. package/dist/lib/castUtils.d.ts +18 -0
  123. package/dist/lib/castUtils.js +81 -0
  124. package/dist/lib/castUtils.js.map +1 -0
  125. package/dist/lib/chainList.d.ts +5 -0
  126. package/dist/lib/chainList.js +86 -0
  127. package/dist/lib/chainList.js.map +1 -0
  128. package/dist/lib/cliParser.d.ts +27 -0
  129. package/dist/lib/cliParser.js +167 -0
  130. package/dist/lib/cliParser.js.map +1 -0
  131. package/dist/lib/commandUtils.d.ts +13 -0
  132. package/dist/lib/commandUtils.js +38 -0
  133. package/dist/lib/commandUtils.js.map +1 -0
  134. package/dist/lib/coreWalletUtils.d.ts +3 -0
  135. package/dist/lib/coreWalletUtils.js +74 -0
  136. package/dist/lib/coreWalletUtils.js.map +1 -0
  137. package/dist/lib/justification.d.ts +90 -0
  138. package/dist/lib/justification.js +577 -0
  139. package/dist/lib/justification.js.map +1 -0
  140. package/dist/lib/ledgerUtils.d.ts +4 -0
  141. package/dist/lib/ledgerUtils.js +258 -0
  142. package/dist/lib/ledgerUtils.js.map +1 -0
  143. package/dist/lib/logger.d.ts +46 -0
  144. package/dist/lib/logger.js +226 -0
  145. package/dist/lib/logger.js.map +1 -0
  146. package/dist/lib/pChainUtils.d.ts +128 -0
  147. package/dist/lib/pChainUtils.js +436 -0
  148. package/dist/lib/pChainUtils.js.map +1 -0
  149. package/dist/lib/pass.d.ts +81 -0
  150. package/dist/lib/pass.js +353 -0
  151. package/dist/lib/pass.js.map +1 -0
  152. package/dist/lib/safeUtils.d.ts +25 -0
  153. package/dist/lib/safeUtils.js +93 -0
  154. package/dist/lib/safeUtils.js.map +1 -0
  155. package/dist/lib/transferUtils.d.ts +643 -0
  156. package/dist/lib/transferUtils.js +141 -0
  157. package/dist/lib/transferUtils.js.map +1 -0
  158. package/dist/lib/utils.d.ts +28 -0
  159. package/dist/lib/utils.js +166 -0
  160. package/dist/lib/utils.js.map +1 -0
  161. package/dist/lib/viemUtils.d.ts +80 -0
  162. package/dist/lib/viemUtils.js +317 -0
  163. package/dist/lib/viemUtils.js.map +1 -0
  164. package/dist/lib/warpUtils.d.ts +76 -0
  165. package/dist/lib/warpUtils.js +448 -0
  166. package/dist/lib/warpUtils.js.map +1 -0
  167. package/dist/middleware.d.ts +75 -0
  168. package/dist/middleware.js +430 -0
  169. package/dist/middleware.js.map +1 -0
  170. package/dist/operator.d.ts +4 -0
  171. package/dist/operator.js +22 -0
  172. package/dist/operator.js.map +1 -0
  173. package/dist/operatorOptIn.d.ts +8 -0
  174. package/dist/operatorOptIn.js +39 -0
  175. package/dist/operatorOptIn.js.map +1 -0
  176. package/dist/rewards.d.ts +116 -0
  177. package/dist/rewards.js +244 -0
  178. package/dist/rewards.js.map +1 -0
  179. package/dist/securityModule.d.ts +8 -0
  180. package/dist/securityModule.js +305 -0
  181. package/dist/securityModule.js.map +1 -0
  182. package/dist/stakingVault.d.ts +184 -0
  183. package/dist/stakingVault.js +1224 -0
  184. package/dist/stakingVault.js.map +1 -0
  185. package/dist/uptime.d.ts +54 -0
  186. package/dist/uptime.js +246 -0
  187. package/dist/uptime.js.map +1 -0
  188. package/dist/vault.d.ts +16 -0
  189. package/dist/vault.js +131 -0
  190. package/dist/vault.js.map +1 -0
  191. package/dist/vaultManager.d.ts +8 -0
  192. package/dist/vaultManager.js +40 -0
  193. package/dist/vaultManager.js.map +1 -0
  194. package/package.json +62 -0
package/dist/cli.js ADDED
@@ -0,0 +1,3183 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ // Temporarly rm warning from SafeSDK dependencies
8
+ const _originalWarn = console.warn.bind(console);
9
+ console.warn = function (...args) {
10
+ const msg = args.join(" ");
11
+ if (msg.includes("gelatonetwork")) {
12
+ return;
13
+ }
14
+ return _originalWarn(...args);
15
+ };
16
+ const extra_typings_1 = require("@commander-js/extra-typings");
17
+ const viem_1 = require("viem");
18
+ const l1_1 = require("./l1");
19
+ const operator_1 = require("./operator");
20
+ const config_1 = require("./config");
21
+ const client_1 = require("./client");
22
+ const logger_1 = require("./lib/logger");
23
+ const vaultManager_1 = require("./vaultManager");
24
+ const vault_1 = require("./vault");
25
+ const delegator_1 = require("./delegator");
26
+ const middleware_1 = require("./middleware");
27
+ const operatorOptIn_1 = require("./operatorOptIn");
28
+ const balancer_1 = require("./balancer");
29
+ const uptime_1 = require("./uptime");
30
+ const rewards_1 = require("./rewards");
31
+ const transferUtils_1 = require("./lib/transferUtils");
32
+ const utils_1 = require("./lib/utils");
33
+ const keyStore_1 = require("./keyStore");
34
+ const cliParser_1 = require("./lib/cliParser");
35
+ const pChainUtils_1 = require("./lib/pChainUtils");
36
+ const ts_belt_1 = require("@mobily/ts-belt");
37
+ const securityModule_1 = require("./securityModule");
38
+ const kiteStaking_1 = require("./kiteStaking");
39
+ const stakingVault_1 = require("./stakingVault");
40
+ const avalanchejs_1 = require("@avalabs/avalanchejs");
41
+ const justification_1 = require("./lib/justification");
42
+ const autoCompletion_1 = require("./lib/autoCompletion");
43
+ const accessControl_1 = require("./accessControl");
44
+ const viemUtils_1 = require("./lib/viemUtils");
45
+ require("./lib/commandUtils");
46
+ const child_process_1 = require("child_process");
47
+ const chainList_1 = require("./lib/chainList");
48
+ const fs_1 = require("fs");
49
+ const package_json_1 = __importDefault(require("../package.json"));
50
+ // Main function to set up the CLI commands
51
+ async function main() {
52
+ const program = new extra_typings_1.Command()
53
+ .name('suzaku-cli')
54
+ .addOption(new extra_typings_1.Option('-n, --network <network>')
55
+ .choices(Object.keys(chainList_1.chainList))
56
+ .default('mainnet'))
57
+ .addOption(new extra_typings_1.Option('-r, --rpc-url <rpcUrl>', 'RPC URL for a custom network (automatically sets --network to custom)'))
58
+ .addOption(new extra_typings_1.Option('-k, --private-key <privateKey>', 'Private key in Hex format')
59
+ .env('PK').argParser(cliParser_1.ParserPrivateKey).conflicts(['secretName', 'ledger']))
60
+ .addOption(new extra_typings_1.Option('-s, --secret-name <secretName>', 'The keystore secret name containing the private key')
61
+ .conflicts(['privateKey', 'ledger'])
62
+ .argParser(cliParser_1.parseSecretName))
63
+ .addOption(new extra_typings_1.Option('-l, --ledger', 'Use Ledger hardware wallet for signing').conflicts(['privateKey', 'secretName']))
64
+ .addOption(new extra_typings_1.Option('-w, --wait <confirmations>', 'Number of confirmations to wait after a write transaction')
65
+ .default(2)
66
+ .argParser(cliParser_1.ParserNumber))
67
+ .addOption(new extra_typings_1.Option("--json", "Output logs in JSON format"))
68
+ .addOption(new extra_typings_1.Option('-y, --yes', 'Automatic yes to prompts'))
69
+ .addOption((0, cliParser_1.OptAddress)('--safe <address>', 'Use safe smart account for transactions'))
70
+ .addOption(new extra_typings_1.Option('--skip-abi-validation', 'Skip the ABI validation for used contract'))
71
+ .addOption(new extra_typings_1.Option('--cast', 'Output equivalent Foundry cast commands instead of executing write transactions').conflicts(['safe']))
72
+ .version(package_json_1.default.version)
73
+ .configureOutput({
74
+ writeOut: (str) => process.stdout.write(str),
75
+ writeErr: (str) => { str.includes('Usage: suzaku-cli') ? process.stdout.write(str) : process.stderr.write(str); },
76
+ });
77
+ // Set cast mode and handle --rpc-url/custom network before any command runs
78
+ program.hook('preSubcommand', async (thisCommand) => {
79
+ const opts = program.opts();
80
+ if (opts.cast)
81
+ (0, viemUtils_1.setCastMode)(true);
82
+ // Block manually private key on mainnet
83
+ if (opts.privateKey && chainList_1.chainList[opts.network].testnet === false) {
84
+ logger_1.logger.error("Using private key on mainnet is not allowed. Use the secret keystore or a ledger instead.");
85
+ process.exit(1);
86
+ }
87
+ if (opts.rpcUrl) {
88
+ await (0, chainList_1.setCustomChainRpcUrl)(opts.rpcUrl);
89
+ thisCommand.setOptionValue('network', 'custom');
90
+ }
91
+ else if (opts.network === 'custom') {
92
+ logger_1.logger.error('Error: --rpc-url is required when using --network custom');
93
+ process.exit(1);
94
+ }
95
+ // Activate json output if --json is provided
96
+ logger_1.logger.setJsonMode(opts.json);
97
+ });
98
+ program.hook("preAction", () => {
99
+ const opts = program.opts();
100
+ // Ensure privateKey is set if opts.secret or ledger is provided
101
+ if (opts.secretName) {
102
+ program.setOptionValue('privateKey', opts.secretName);
103
+ }
104
+ else if (opts.ledger) {
105
+ program.setOptionValue('privateKey', 'ledger');
106
+ }
107
+ });
108
+ program
109
+ .command('verify-abi')
110
+ .description('Verify that a contract at a given address matches the expected Suzaku ABI (5% tolerance)')
111
+ .addArgument((0, cliParser_1.ArgAddress)("address", "Contract address to test"))
112
+ .argument('abi', 'ABI name to test')
113
+ .asyncAction(async (config, address, abi) => {
114
+ await config.contracts[abi](address);
115
+ logger_1.logger.log(`Verified ABI for contract ${abi} at address ${address} ✅`);
116
+ });
117
+ /* --------------------------------------------------
118
+ * Common Args
119
+ * -------------------------------------------------- */
120
+ // Contract
121
+ const argValidatorManagerAddress = (0, cliParser_1.ArgAddress)("validatorManagerAddress", "L1 validator manager contract address");
122
+ const argBalancerAddress = (0, cliParser_1.ArgAddress)("balancerAddress", "Balancer validator manager contract address");
123
+ const argPoaSecurityModuleAddress = (0, cliParser_1.ArgAddress)("poaSecurityModuleAddress", "POA Security Module contract address");
124
+ const argMiddlewareAddress = (0, cliParser_1.ArgAddress)("middlewareAddress", "Middleware contract address");
125
+ const argMiddlewareVaultManagerAddress = (0, cliParser_1.ArgAddress)("middlewareVaultManagerAddress", "Middleware vault manager contract address");
126
+ const argVaultAddress = (0, cliParser_1.ArgAddress)("vaultAddress", "Vault contract address");
127
+ const argUptimeTrackerAddress = (0, cliParser_1.ArgAddress)("uptimeTrackerAddress", "UptimeTracker contract address");
128
+ const argRewardsAddress = (0, cliParser_1.ArgAddress)("rewardsAddress", "Rewards contract address");
129
+ const argRewardTokenAddress = (0, cliParser_1.ArgAddress)("rewardTokenAddress", "Reward token contract address");
130
+ const optKiteStakingManagerAddress = (0, cliParser_1.OptAddress)("--staking-manager-address <address>", "KiteStakingManager contract address");
131
+ const optStakingVaultAddress = (0, cliParser_1.OptAddress)("--staking-vault-address <address>", "Staking vault contract address");
132
+ const argAccessControlAddress = (0, cliParser_1.ArgAddress)("accessControlAddress", "A contract address with AccessControl functionalities");
133
+ // EOA
134
+ const argOperatorAddress = (0, cliParser_1.ArgAddress)("operator", "Operator address");
135
+ /* --------------------------------------------------
136
+ * Generic L1 Commands
137
+ * -------------------------------------------------- */
138
+ // topUpAllOperatorNodes
139
+ program
140
+ .command("top-up-l1-validators")
141
+ .description("Top up all/selected l1 validators to meet a target continuous fee balance")
142
+ .addArgument((0, cliParser_1.ArgCB58)("subnetID", "Subnet ID of the L1"))
143
+ .argument("targetBalance", "Target continuous fee balance per validator (in AVAX)")
144
+ .addOption(new extra_typings_1.Option("--node-id <nodeId>", "Add a validator to be topped up").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserNodeID)))
145
+ .asyncAction({ signer: true }, async (config, subnetID, targetBalance, options) => {
146
+ const opts = program.opts();
147
+ const client = await (0, client_1.generateClient)(opts.network, opts.privateKey, opts.safe);
148
+ const targetBalanceWei = (0, viem_1.parseUnits)(targetBalance, 9); // AVAX has 9 decimals
149
+ if (targetBalanceWei <= BigInt(1e7)) { // 0.01 AVAX min
150
+ throw new Error("Target balance must be greater than 0.01 AVAX");
151
+ }
152
+ const validators = await (0, pChainUtils_1.getCurrentValidators)(config.client, subnetID);
153
+ const validatorsToTopUp = validators.reduce((acc, validator) => {
154
+ if (options.nodeId && options.nodeId.length > 0 && !options.nodeId.includes(validator.nodeID)) {
155
+ return acc;
156
+ }
157
+ if (validator.balance < Number(targetBalanceWei) - 1e7) { // 0.01 AVAX min diff
158
+ acc.push({
159
+ validationId: validator.validationID,
160
+ topup: targetBalanceWei - BigInt(validator.balance),
161
+ });
162
+ }
163
+ return acc;
164
+ }, []);
165
+ const totalTopUp = validatorsToTopUp.reduce((acc, v) => acc + v.topup, 0n);
166
+ if (validatorsToTopUp.length === 0) {
167
+ logger_1.logger.log("All l1 validators have sufficient balance. No top-up needed.");
168
+ logger_1.logger.addData('total_amount', 0);
169
+ logger_1.logger.addData('validators', []);
170
+ return;
171
+ }
172
+ logger_1.logger.log(`${validatorsToTopUp.length} validators to top-up:`);
173
+ await (0, transferUtils_1.requirePChainBallance)(config.client, totalTopUp + BigInt(2e4) * BigInt(validatorsToTopUp.length), opts.yes); // extra 20000 for fees
174
+ if (!opts.yes) {
175
+ const response = await logger_1.logger.prompt(`Proceed with topping up validators? (y/n): `);
176
+ if (response.toLowerCase() !== 'y') {
177
+ logger_1.logger.log("Operation cancelled by user.");
178
+ process.exit(0);
179
+ }
180
+ }
181
+ for (const { validationId, topup } of validatorsToTopUp) {
182
+ logger_1.logger.log(`\nTopping up validator ${validationId}`);
183
+ const amount = Number(topup) / 1e9;
184
+ (0, ts_belt_1.pipe)(await (0, pChainUtils_1.increasePChainValidatorBalance)(config.client, amount, validationId, false), ts_belt_1.R.tapError(err => { logger_1.logger.error(err); process.exit(1); }));
185
+ }
186
+ logger_1.logger.log("\nCompleted top-up of validators.");
187
+ logger_1.logger.addData('total_amount', totalTopUp);
188
+ logger_1.logger.addData('validators', validatorsToTopUp);
189
+ });
190
+ /* --------------------------------------------------
191
+ * L1 REGISTRY COMMANDS
192
+ * -------------------------------------------------- */
193
+ const l1RegistryCmd = program
194
+ .command("l1-registry")
195
+ .description("Commands to interact with the Suzaku L1 Registry contract");
196
+ l1RegistryCmd
197
+ .command("register")
198
+ .description("Register a new L1 in the L1 registry")
199
+ .addArgument(argMiddlewareAddress)
200
+ .addArgument((0, cliParser_1.ArgURI)("metadataUrl", "Metadata URL for the L1"))
201
+ .asyncAction({ signer: true }, async (config, l1Middleware, metadataUrl) => {
202
+ const middleware = await config.contracts.L1Middleware(l1Middleware);
203
+ const balancerAddress = await middleware.read.BALANCER();
204
+ // instantiate L1Registry and call
205
+ const l1Registry = await config.contracts.L1Registry();
206
+ await (0, l1_1.registerL1)(l1Registry, balancerAddress, l1Middleware, metadataUrl, config.client.account);
207
+ });
208
+ l1RegistryCmd
209
+ .command("get-all")
210
+ .description("List all L1s registered in the L1 registry")
211
+ .asyncAction(async (config) => {
212
+ const l1Registry = await config.contracts.L1Registry();
213
+ const l1s = await l1Registry.read.getAllL1s();
214
+ // l1s: [balancerAddress[], middleware[], metadataUrl[]]
215
+ const data = [];
216
+ for (let i = 0; i < l1s[0].length; i++) {
217
+ data.push({
218
+ MetadataUrl: l1s[2][i],
219
+ Balancer: l1s[0][i],
220
+ Middleware: l1s[1][i],
221
+ });
222
+ }
223
+ logger_1.logger.logJsonTree(data);
224
+ });
225
+ l1RegistryCmd
226
+ .command("set-metadata-url")
227
+ .description("Set metadata URL for an L1 in the L1 registry")
228
+ .addArgument(argValidatorManagerAddress)
229
+ .addArgument((0, cliParser_1.ArgURI)("metadataUrl", "New metadata URL"))
230
+ .asyncAction({ signer: true }, async (config, l1Address, metadataUrl) => {
231
+ const l1Reg = await config.contracts.L1Registry();
232
+ await (0, l1_1.setL1MetadataUrl)(l1Reg, l1Address, metadataUrl);
233
+ });
234
+ l1RegistryCmd
235
+ .command("set-middleware")
236
+ .description("Set middleware address for an L1 in the L1 registry")
237
+ .addArgument(argValidatorManagerAddress)
238
+ .addArgument((0, cliParser_1.ArgAddress)("l1Middleware", "New L1 middleware address"))
239
+ .asyncAction({ signer: true }, async (config, l1Address, l1Middleware) => {
240
+ const l1Reg2 = await config.contracts.L1Registry();
241
+ await (0, l1_1.setL1Middleware)(l1Reg2, l1Address, l1Middleware);
242
+ });
243
+ /* --------------------------------------------------
244
+ * OPERATOR REGISTRY COMMANDS
245
+ * -------------------------------------------------- */
246
+ const operatorRegistryCmd = program
247
+ .command("operator-registry")
248
+ .description("Commands to interact with the Suzaku Operator Registry contract");
249
+ operatorRegistryCmd
250
+ .command("register")
251
+ .description("Register a new operator in the operator registry")
252
+ .addArgument((0, cliParser_1.ArgURI)("metadataUrl", "Operator metadata URL"))
253
+ .asyncAction({ signer: true }, async (config, metadataUrl) => {
254
+ const opReg = await config.contracts.OperatorRegistry();
255
+ await (0, operator_1.registerOperator)(opReg, metadataUrl);
256
+ });
257
+ operatorRegistryCmd
258
+ .command("get-all")
259
+ .description("List all operators registered in the operator registry")
260
+ .asyncAction(async (config) => {
261
+ const opReg2 = await config.contracts.OperatorRegistry();
262
+ await (0, operator_1.listOperators)(opReg2);
263
+ });
264
+ /* --------------------------------------------------
265
+ * VAULT MANAGER
266
+ * -------------------------------------------------- */
267
+ const vaultManagerCmd = program
268
+ .command("vault-manager")
269
+ .description("Commands to interact with the Vault Manager contract of an L1");
270
+ vaultManagerCmd
271
+ .command("register-vault-l1")
272
+ .description("Register a vault for L1 staking")
273
+ .addArgument(argMiddlewareVaultManagerAddress)
274
+ .addArgument(argVaultAddress)
275
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClass", "Collateral class ID"))
276
+ .argument("maxLimit", "Maximum limit (in decimal format)")
277
+ .asyncAction({ signer: true }, async (config, middlewareVaultManagerAddress, vaultAddress, collateralClass, maxLimit) => {
278
+ // instantiate VaultManager contract
279
+ const vaultManager = await config.contracts.VaultManager(middlewareVaultManagerAddress);
280
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
281
+ const maxLimitWei = (0, viem_1.parseUnits)(maxLimit, await vault.read.decimals());
282
+ await (0, vaultManager_1.registerVaultL1)(vaultManager, vaultAddress, collateralClass, maxLimitWei, config.client.account);
283
+ });
284
+ vaultManagerCmd
285
+ .command("update-vault-max-l1-limit")
286
+ .description("Update the maximum L1 limit for a vault")
287
+ .addArgument(argMiddlewareVaultManagerAddress)
288
+ .addArgument(argVaultAddress)
289
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClass", "Collateral class ID"))
290
+ .argument("maxLimit", "Maximum limit")
291
+ .asyncAction({ signer: true }, async (config, middlewareVaultManagerAddress, vaultAddress, collateralClass, maxLimit) => {
292
+ const vaultManager = await config.contracts.VaultManager(middlewareVaultManagerAddress);
293
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
294
+ const maxLimitWei = (0, viem_1.parseUnits)(maxLimit, await vault.read.decimals());
295
+ await (0, vaultManager_1.updateVaultMaxL1Limit)(vaultManager, vaultAddress, collateralClass, maxLimitWei, config.client.account);
296
+ });
297
+ vaultManagerCmd
298
+ .command("remove-vault")
299
+ .description("Remove a vault from L1 staking")
300
+ .addArgument(argMiddlewareVaultManagerAddress)
301
+ .addArgument(argVaultAddress)
302
+ .asyncAction({ signer: true }, async (config, middlewareVaultManager, vaultAddress) => {
303
+ const vaultManager = await config.contracts.VaultManager(middlewareVaultManager);
304
+ await (0, vaultManager_1.removeVault)(vaultManager, vaultAddress, config.client.account);
305
+ });
306
+ vaultManagerCmd
307
+ .command("get-vault-count")
308
+ .description("Get the number of vaults registered for L1 staking")
309
+ .addArgument(argMiddlewareVaultManagerAddress)
310
+ .asyncAction(async (config, middlewareVaultManager) => {
311
+ const vaultManager = await config.contracts.VaultManager(middlewareVaultManager);
312
+ await (0, vaultManager_1.getVaultCount)(vaultManager);
313
+ });
314
+ vaultManagerCmd
315
+ .command("get-vault-at-with-times")
316
+ .description("Get the vault address at a specific index along with its registration and removal times")
317
+ .addArgument(argMiddlewareVaultManagerAddress)
318
+ .addArgument((0, cliParser_1.ArgBigInt)("index", "Vault index"))
319
+ .asyncAction(async (config, middlewareVaultManager, index) => {
320
+ const vaultManager = await config.contracts.VaultManager(middlewareVaultManager);
321
+ await (0, vaultManager_1.getVaultAtWithTimes)(vaultManager, index);
322
+ });
323
+ vaultManagerCmd
324
+ .command("get-vault-collateral-class")
325
+ .description("Get the collateral class ID associated with a vault")
326
+ .addArgument(argMiddlewareVaultManagerAddress)
327
+ .addArgument(argVaultAddress)
328
+ .asyncAction(async (config, middlewareVaultManager, vaultAddress) => {
329
+ const vaultManager = await config.contracts.VaultManager(middlewareVaultManager);
330
+ await (0, vaultManager_1.getVaultCollateralClass)(vaultManager, vaultAddress);
331
+ });
332
+ /* --------------------------------------------------
333
+ * VAULT DEPOSIT/WITHDRAW/CLAIM/GRANT
334
+ * -------------------------------------------------- */
335
+ const vaultCmd = program
336
+ .command("vault")
337
+ .description("Commands to interact with a Vault and L1 Re-stake Delegator contracts");
338
+ vaultCmd
339
+ .command("deposit")
340
+ .description("Deposit tokens into the vault")
341
+ .addArgument(argVaultAddress)
342
+ .argument("amount", "Amount of token to deposit in the vault")
343
+ .addOption(new extra_typings_1.Option("--onBehalfOf <behalfOf>", "Optional onBehalfOf address").argParser(cliParser_1.ParserAddress))
344
+ .asyncAction({ signer: true }, async (config, vaultAddress, amount, options) => {
345
+ const onBehalfOf = options.onBehalfOf ?? config.client.account.address;
346
+ await (0, vault_1.depositVault)(config, vaultAddress, onBehalfOf, amount);
347
+ });
348
+ vaultCmd
349
+ .command("withdraw")
350
+ .description("Withdraw tokens from the vault")
351
+ .addArgument(argVaultAddress)
352
+ .argument("amount", "Amount of token to withdraw in the vault")
353
+ .addOption(new extra_typings_1.Option("--claimer <claimer>", "Optional claimer").argParser(cliParser_1.ParserAddress))
354
+ .asyncAction({ signer: true }, async (config, vaultAddress, amount, options) => {
355
+ const claimer = options.claimer ?? config.client.account.address;
356
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
357
+ const amountWei = (0, viem_1.parseUnits)(amount, await vault.read.decimals());
358
+ await (0, vault_1.withdrawVault)(vault, claimer, amountWei);
359
+ });
360
+ vaultCmd
361
+ .command("claim")
362
+ .description("Claim withdrawn tokens from the vault for a specific epoch")
363
+ .addArgument(argVaultAddress)
364
+ .addArgument((0, cliParser_1.ArgBigInt)("epoch", "Epoch number"))
365
+ .addOption(new extra_typings_1.Option("--recipient <recipient>", "Optional recipient").argParser(cliParser_1.ParserAddress))
366
+ .asyncAction({ signer: true }, async (config, vaultAddress, epoch, options) => {
367
+ const recipient = options.recipient ?? config.client.account.address;
368
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
369
+ await (0, vault_1.claimVault)(vault, recipient, epoch);
370
+ });
371
+ vaultCmd
372
+ .command("grant-staker-role")
373
+ .description("Grant staker role on a vault to an account")
374
+ .addArgument(argVaultAddress)
375
+ .addArgument((0, cliParser_1.ArgAddress)("account", "Account to grant the role to"))
376
+ .asyncAction({ signer: true }, async (config, vaultAddress, account) => {
377
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
378
+ await vault.safeWrite.grantRole([await vault.read.DEPOSITOR_WHITELIST_ROLE(), account], {
379
+ chain: null,
380
+ account: config.client.account,
381
+ });
382
+ logger_1.logger.log(`Granted staker role to ${account} on vault (${await vault.read.name()}) ${vaultAddress}`);
383
+ });
384
+ vaultCmd
385
+ .command("revoke-staker-role")
386
+ .description("Revoke staker role on a vault from an account")
387
+ .addArgument(argVaultAddress)
388
+ .addArgument((0, cliParser_1.ArgAddress)("account", "Account to revoke the role from"))
389
+ .asyncAction({ signer: true }, async (config, vaultAddress, account) => {
390
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
391
+ await vault.safeWrite.revokeRole([await vault.read.DEPOSITOR_WHITELIST_ROLE(), account], {
392
+ chain: null,
393
+ account: config.client.account,
394
+ });
395
+ logger_1.logger.log(`Revoked staker role from ${account} on vault (${await vault.read.name()}) ${vaultAddress}`);
396
+ });
397
+ vaultCmd
398
+ .command("collateral-deposit")
399
+ .description("Approve and deposit tokens into the collateral contract associated with a vault")
400
+ .addArgument((0, cliParser_1.ArgAddress)("collateralAddress", "Collateral contract address"))
401
+ .argument("amount", "Amount of token to deposit in the collateral")
402
+ .asyncAction({ signer: true }, async (_, collateralAddress, amount) => {
403
+ const opts = program.opts();
404
+ const client = await (0, client_1.generateClient)(opts.network, opts.privateKey, opts.safe);
405
+ const config = (0, config_1.getConfig)(client, opts.wait, true); // skip abi validation as erc20 are commonly different
406
+ await (0, vault_1.approveAndDepositCollateral)(config, collateralAddress, amount);
407
+ });
408
+ // setIsDepositLimit
409
+ vaultCmd
410
+ .command("set-deposit-limit")
411
+ .description("Set deposit limit for a vault (0 will disable the limit)")
412
+ .addArgument(argVaultAddress)
413
+ .argument("limit", "Deposit limit amount")
414
+ .asyncAction({ signer: true }, async (config, vaultAddress, limit) => {
415
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
416
+ const limitWei = (0, viem_1.parseUnits)(limit, await vault.read.decimals());
417
+ const isLimitShouldBeEnabled = limitWei > 0n;
418
+ const isLimitEnabled = await vault.read.isDepositLimit();
419
+ if (isLimitShouldBeEnabled !== isLimitEnabled) {
420
+ await vault.safeWrite.setIsDepositLimit([isLimitShouldBeEnabled], {
421
+ chain: null,
422
+ account: config.client.account,
423
+ });
424
+ logger_1.logger.log(`Set deposit limit enabled to ${isLimitShouldBeEnabled} for vault (${await vault.read.name()}) ${vaultAddress}`);
425
+ }
426
+ await vault.safeWrite.setDepositLimit([limitWei], {
427
+ chain: null,
428
+ account: config.client.account,
429
+ });
430
+ logger_1.logger.log(`Set deposit limit to ${limit} for vault (${await vault.read.name()}) ${vaultAddress}`);
431
+ });
432
+ // increaseLimit of the collateral
433
+ vaultCmd
434
+ .command("collateral-increase-limit")
435
+ .description("Set deposit limit for a collateral")
436
+ .addArgument(argVaultAddress)
437
+ .argument("limit", "Deposit limit amount")
438
+ .asyncAction({ signer: true }, async (config, vaultAddress, limit) => {
439
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
440
+ const collateralAddress = await vault.read.collateral();
441
+ const collateral = await config.contracts.DefaultCollateral(collateralAddress);
442
+ const limitWei = (0, viem_1.parseUnits)(limit, await collateral.read.decimals());
443
+ await collateral.safeWrite.increaseLimit([limitWei], {
444
+ chain: null,
445
+ account: config.client.account,
446
+ });
447
+ logger_1.logger.log(`Collateral (${collateralAddress}) limit increased to ${limit} (${await collateral.read.name()})`);
448
+ });
449
+ /* --------------------------------------------------
450
+ * VAULT READ COMMANDS
451
+ * -------------------------------------------------- */
452
+ vaultCmd
453
+ .command("get-collateral")
454
+ .description("Get the collateral token address of a vault")
455
+ .addArgument(argVaultAddress)
456
+ .asyncAction(async (config, vaultAddress) => {
457
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
458
+ await (0, vault_1.getVaultCollateral)(vault);
459
+ });
460
+ vaultCmd
461
+ .command("get-delegator")
462
+ .description("Get the delegator address of a vault")
463
+ .addArgument(argVaultAddress)
464
+ .asyncAction(async (config, vaultAddress) => {
465
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
466
+ const delegator = await (0, vault_1.getVaultDelegator)(vault);
467
+ logger_1.logger.log("Vault delegator:", delegator);
468
+ });
469
+ vaultCmd
470
+ .command("get-balance")
471
+ .description("Get vault token balance for an account")
472
+ .addArgument(argVaultAddress)
473
+ .addOption(new extra_typings_1.Option("--account <account>", "Account to check balance for").argParser(cliParser_1.ParserAddress))
474
+ .asyncAction({ signer: true }, async (config, vaultAddress, options) => {
475
+ const account = options.account ?? config.client.account.address;
476
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
477
+ await (0, vault_1.getVaultBalanceOf)(vault, account);
478
+ });
479
+ vaultCmd
480
+ .command("get-active-balance")
481
+ .description("Get active vault balance for an account")
482
+ .addArgument(argVaultAddress)
483
+ .addOption(new extra_typings_1.Option("--account <account>", "Account to check balance for").argParser(cliParser_1.ParserAddress))
484
+ .asyncAction({ signer: true }, async (config, vaultAddress, options) => {
485
+ const account = options.account ?? config.client.account.address;
486
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
487
+ await (0, vault_1.getVaultActiveBalanceOf)(vault, account);
488
+ });
489
+ vaultCmd
490
+ .command("get-total-supply")
491
+ .description("Get total supply of vault tokens")
492
+ .addArgument(argVaultAddress)
493
+ .asyncAction(async (config, vaultAddress) => {
494
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
495
+ await (0, vault_1.getVaultTotalSupply)(vault);
496
+ });
497
+ vaultCmd
498
+ .command("get-withdrawal-shares")
499
+ .description("Get withdrawal shares for an account at a specific epoch")
500
+ .addArgument(argVaultAddress)
501
+ .addArgument((0, cliParser_1.ArgBigInt)("epoch", "Epoch number"))
502
+ .addOption(new extra_typings_1.Option("--account <account>", "Account to check").argParser(cliParser_1.ParserAddress))
503
+ .asyncAction({ signer: true }, async (config, vaultAddress, epoch, options) => {
504
+ const account = options.account ?? config.client.account.address;
505
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
506
+ await (0, vault_1.getVaultWithdrawalSharesOf)(vault, epoch, account);
507
+ });
508
+ vaultCmd
509
+ .command("get-withdrawals")
510
+ .description("Get withdrawal amount for an account at a specific epoch")
511
+ .addArgument(argVaultAddress)
512
+ .addArgument((0, cliParser_1.ArgBigInt)("epoch", "Epoch number"))
513
+ .addOption(new extra_typings_1.Option("--account <account>", "Account to check").argParser(cliParser_1.ParserAddress))
514
+ .asyncAction({ signer: true }, async (config, vaultAddress, epoch, options) => {
515
+ const account = options.account ?? config.client.account.address;
516
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
517
+ await (0, vault_1.getVaultWithdrawalsOf)(vault, epoch, account);
518
+ });
519
+ // Get deposit limit
520
+ vaultCmd
521
+ .command("get-deposit-limit")
522
+ .description("Get deposit limit for a vault")
523
+ .addArgument(argVaultAddress)
524
+ .asyncAction(async (config, vaultAddress) => {
525
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
526
+ const limit = await vault.read.depositLimit();
527
+ const isLimitEnabled = await vault.read.isDepositLimit();
528
+ logger_1.logger.log(`Deposit limit for vault ${vaultAddress}: ${(0, viem_1.formatUnits)(limit, await vault.read.decimals())} (enabled: ${isLimitEnabled})`);
529
+ });
530
+ /* --------------------------------------------------
531
+ * L1RestakeDelegator (set-l1-limit / set-operator-l1-shares)
532
+ * -------------------------------------------------- */
533
+ vaultCmd
534
+ .command("set-l1-limit")
535
+ .description("Set the L1 limit for a vault's delegator")
536
+ .addArgument(argVaultAddress)
537
+ .addArgument(argValidatorManagerAddress)
538
+ .argument("limit", "Limit amount")
539
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClass", "Collateral class ID"))
540
+ .asyncAction({ signer: true }, async (config, vaultAddress, l1Address, limit, collateralClass) => {
541
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
542
+ const delegatorAddress = await vault.read.delegator();
543
+ // instantiate L1RestakeDelegator contract
544
+ const delegator = await config.contracts.L1RestakeDelegator(delegatorAddress);
545
+ const limitWei = (0, viem_1.parseUnits)(limit, await vault.read.decimals());
546
+ await (0, delegator_1.setL1Limit)(delegator, l1Address, collateralClass, limitWei);
547
+ });
548
+ vaultCmd
549
+ .command("set-operator-l1-shares")
550
+ .description("Set the L1 shares for an operator in a delegator")
551
+ .addArgument(argVaultAddress)
552
+ .addArgument(argValidatorManagerAddress)
553
+ .addArgument(argOperatorAddress)
554
+ .addArgument((0, cliParser_1.ArgBigInt)("shares", "Shares amount"))
555
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClass", "Collateral class ID"))
556
+ .asyncAction({ signer: true }, async (config, vaultAddress, l1Address, operatorAddress, shares, collateralClass) => {
557
+ // instantiate L1RestakeDelegator contract
558
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
559
+ const delegatorAddress = await vault.read.delegator();
560
+ const delegator = await config.contracts.L1RestakeDelegator(delegatorAddress);
561
+ await (0, delegator_1.setOperatorL1Shares)(delegator, l1Address, collateralClass, operatorAddress, shares);
562
+ });
563
+ vaultCmd
564
+ .command("get-l1-limit")
565
+ .description("Get L1 limit for a vault's delegator")
566
+ .addArgument(argVaultAddress)
567
+ .addArgument(argValidatorManagerAddress)
568
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClass", "Collateral class ID"))
569
+ .asyncAction(async (config, vaultAddress, l1Address, collateralClass) => {
570
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
571
+ const delegatorAddress = await vault.read.delegator();
572
+ // instantiate L1RestakeDelegator contract
573
+ const delegator = await config.contracts.L1RestakeDelegator(delegatorAddress);
574
+ const limit = await delegator.read.l1Limit([l1Address, collateralClass]);
575
+ logger_1.logger.log(`L1 limit for vault ${vaultAddress} on L1 ${l1Address} (collateral class ${collateralClass}): ${(0, viem_1.formatUnits)(limit, await vault.read.decimals())}`);
576
+ });
577
+ vaultCmd
578
+ .command("get-operator-l1-shares")
579
+ .description("Get L1 shares for an operator in a vault's delegator")
580
+ .addArgument(argVaultAddress)
581
+ .addArgument(argValidatorManagerAddress)
582
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClass", "Collateral class ID"))
583
+ .addArgument(argOperatorAddress)
584
+ .asyncAction(async (config, vaultAddress, l1Address, collateralClass, operatorAddress) => {
585
+ const vault = await config.contracts.VaultTokenized(vaultAddress);
586
+ const delegatorAddress = await vault.read.delegator();
587
+ // instantiate L1RestakeDelegator contract
588
+ const delegator = await config.contracts.L1RestakeDelegator(delegatorAddress);
589
+ const shares = await delegator.read.operatorL1Shares([l1Address, collateralClass, operatorAddress]);
590
+ logger_1.logger.log(`L1 shares for operator ${operatorAddress} in vault ${vaultAddress} on L1 ${l1Address} (collateral class ${collateralClass}): ${shares}`);
591
+ });
592
+ /* --------------------------------------------------
593
+ * MIDDLEWARE
594
+ * -------------------------------------------------- */
595
+ const middlewareCmd = program
596
+ .command("middleware")
597
+ .description("Commands to interact with the L1 Middleware contract");
598
+ // Add secondary collateral class
599
+ middlewareCmd
600
+ .command("add-collateral-class")
601
+ .description("Add a new collateral class to the middleware")
602
+ .addArgument(argMiddlewareAddress)
603
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClassId", "Collateral class ID"))
604
+ .argument("minValidatorStake", "Minimum validator stake amount")
605
+ .argument("maxValidatorStake", "Maximum validator stake amount")
606
+ .addArgument((0, cliParser_1.ArgAddress)("initialCollateral", "Initial collateral address"))
607
+ .asyncAction({ signer: true }, async (config, middlewareAddress, collateralClassId, minValidatorStake, maxValidatorStake, initialCollateral) => {
608
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
609
+ const collateral = await config.contracts.DefaultCollateral(initialCollateral);
610
+ const decimals = await collateral.read.decimals();
611
+ const minStakeWei = (0, viem_1.parseUnits)(minValidatorStake, decimals);
612
+ const maxStakeWei = (0, viem_1.parseUnits)(maxValidatorStake, decimals);
613
+ await middlewareSvc.safeWrite.addCollateralClass([collateralClassId, minStakeWei, maxStakeWei, initialCollateral], {
614
+ chain: null,
615
+ account: config.client.account,
616
+ });
617
+ logger_1.logger.log(`Added collateral class ${collateralClassId} with min stake ${minValidatorStake} and max stake ${maxValidatorStake} using collateral at ${initialCollateral}`);
618
+ });
619
+ // Add collateral to class
620
+ middlewareCmd
621
+ .command("add-collateral-to-class")
622
+ .description("Add a new collateral address to an existing collateral class")
623
+ .addArgument(argMiddlewareAddress)
624
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClassId", "Collateral class ID"))
625
+ .addArgument((0, cliParser_1.ArgAddress)("collateralAddress", "Collateral address to add"))
626
+ .asyncAction({ signer: true }, async (config, middlewareAddress, collateralClassId, collateralAddress) => {
627
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
628
+ await middlewareSvc.safeWrite.addAssetToClass([collateralClassId, collateralAddress], {
629
+ chain: null,
630
+ account: config.client.account,
631
+ });
632
+ logger_1.logger.log(`Added collateral ${collateralAddress} to class ${collateralClassId}`);
633
+ });
634
+ // removeAssetFromClass
635
+ middlewareCmd
636
+ .command("remove-collateral-from-class")
637
+ .description("Remove a collateral address from an existing collateral class")
638
+ .addArgument(argMiddlewareAddress)
639
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClassId", "Collateral class ID"))
640
+ .addArgument((0, cliParser_1.ArgAddress)("collateralAddress", "Collateral address to remove"))
641
+ .asyncAction({ signer: true }, async (config, middlewareAddress, collateralClassId, collateralAddress) => {
642
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
643
+ const tx = await middlewareSvc.safeWrite.removeAssetFromClass([collateralClassId, collateralAddress], {
644
+ chain: null,
645
+ account: config.client.account,
646
+ });
647
+ logger_1.logger.log(`Removed collateral ${collateralAddress} from class ${collateralClassId}`);
648
+ logger_1.logger.log("tx hash:", tx);
649
+ });
650
+ // removeCollateralClass
651
+ middlewareCmd
652
+ .command("remove-collateral-class")
653
+ .description("Remove an existing secondary collateral class")
654
+ .addArgument(argMiddlewareAddress)
655
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClassId", "Collateral class ID"))
656
+ .asyncAction({ signer: true }, async (config, middlewareAddress, collateralClassId) => {
657
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
658
+ await middlewareSvc.safeWrite.removeCollateralClass([collateralClassId], {
659
+ chain: null,
660
+ account: config.client.account,
661
+ });
662
+ logger_1.logger.log(`Removed collateral class ${collateralClassId}`);
663
+ });
664
+ // activateSecondaryCollateralClass
665
+ middlewareCmd
666
+ .command("activate-collateral-class")
667
+ .description("Activate a secondary collateral class")
668
+ .addArgument(argMiddlewareAddress)
669
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClassId", "Collateral class ID"))
670
+ .asyncAction({ signer: true }, async (config, middlewareAddress, collateralClassId) => {
671
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
672
+ await middlewareSvc.safeWrite.activateSecondaryCollateralClass([collateralClassId], {
673
+ chain: null,
674
+ account: config.client.account,
675
+ });
676
+ logger_1.logger.log(`Activated collateral class ${collateralClassId}`);
677
+ });
678
+ // deactivateSecondaryCollateralClass
679
+ middlewareCmd
680
+ .command("deactivate-collateral-class")
681
+ .description("Deactivate a secondary collateral class")
682
+ .addArgument(argMiddlewareAddress)
683
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClassId", "Collateral class ID"))
684
+ .asyncAction({ signer: true }, async (config, middlewareAddress, collateralClassId) => {
685
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
686
+ await middlewareSvc.safeWrite.deactivateSecondaryCollateralClass([collateralClassId], {
687
+ chain: null,
688
+ account: config.client.account,
689
+ });
690
+ logger_1.logger.log(`Deactivated collateral class ${collateralClassId}`);
691
+ });
692
+ // Register operator
693
+ middlewareCmd
694
+ .command("register-operator")
695
+ .description("Register an operator to operate on this L1")
696
+ .addArgument(argMiddlewareAddress)
697
+ .addArgument(argOperatorAddress)
698
+ .asyncAction({ signer: true }, async (config, middlewareAddress, operator) => {
699
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
700
+ await (0, middleware_1.middlewareRegisterOperator)(middlewareSvc, operator);
701
+ });
702
+ // Disable operator
703
+ middlewareCmd
704
+ .command("disable-operator")
705
+ .description("Disable an operator to prevent it from operating on this L1")
706
+ .addArgument(argMiddlewareAddress)
707
+ .addArgument(argOperatorAddress)
708
+ .asyncAction({ signer: true }, async (config, middlewareAddress, operator) => {
709
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
710
+ await (0, middleware_1.middlewareDisableOperator)(middlewareSvc, operator);
711
+ });
712
+ // Remove operator
713
+ middlewareCmd
714
+ .command("remove-operator")
715
+ .description("Remove an operator from this L1")
716
+ .addArgument(argMiddlewareAddress)
717
+ .addArgument(argOperatorAddress)
718
+ .asyncAction({ signer: true }, async (config, middlewareAddress, operator) => {
719
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
720
+ await (0, middleware_1.middlewareRemoveOperator)(middlewareSvc, operator);
721
+ });
722
+ // Process node stake cache
723
+ middlewareCmd
724
+ .command("process-node-stake-cache")
725
+ .description("Manually process node stake cache for one or more epochs")
726
+ .addArgument(argMiddlewareAddress)
727
+ .addOption(new extra_typings_1.Option("--epochs <epochs>", "Number of epochs to process (default: all)").default(0).argParser(cliParser_1.ParserNumber))
728
+ .addOption(new extra_typings_1.Option("--loop-epochs <count>", "Loop through multiple epochs, processing --epochs at a time").argParser(cliParser_1.ParserNumber))
729
+ .addOption(new extra_typings_1.Option("--delay <milliseconds>", "Delay between loop iterations in milliseconds (default: 1000)").default(1000).argParser(cliParser_1.ParserNumber))
730
+ .asyncAction({ signer: true }, async (config, middlewareAddress, options) => {
731
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
732
+ let epochsPerCall;
733
+ let loopCount;
734
+ if (options.epochs || options.loopEpochs) { // Fully specified by user
735
+ epochsPerCall = options.epochs || 1;
736
+ loopCount = options.loopEpochs || 1;
737
+ }
738
+ else { // Automatic calculation
739
+ epochsPerCall = await middlewareSvc.read.getCurrentEpoch() - await middlewareSvc.read.lastGlobalNodeStakeUpdateEpoch();
740
+ loopCount = epochsPerCall > 50 ? Math.ceil(epochsPerCall / 50) : 1; // Limit number of epochs processed in a single call to avoid gas issues
741
+ epochsPerCall = Math.ceil(epochsPerCall / loopCount);
742
+ }
743
+ logger_1.logger.log(`Processing node stake cache: ${loopCount} iterations of ${epochsPerCall} epoch(s) each`);
744
+ for (let i = 0; i < loopCount; i++) {
745
+ logger_1.logger.log(`\nIteration ${i + 1}/${loopCount}`);
746
+ await (0, middleware_1.middlewareManualProcessNodeStakeCache)(middlewareSvc, epochsPerCall);
747
+ if (i < loopCount - 1 && options.delay > 0) {
748
+ logger_1.logger.log(`Waiting ${options.delay}ms before next iteration...`);
749
+ await new Promise(resolve => setTimeout(resolve, options.delay));
750
+ }
751
+ }
752
+ logger_1.logger.log(`\nCompleted processing ${loopCount * epochsPerCall} total epochs`);
753
+ });
754
+ // Add node
755
+ middlewareCmd
756
+ .command("add-node")
757
+ .description("Add a new node to an L1")
758
+ .addArgument(argMiddlewareAddress)
759
+ .addArgument((0, cliParser_1.ArgNodeID)())
760
+ .addArgument((0, cliParser_1.ArgHex)("blsKey", "BLS public key"))
761
+ .addOption(new extra_typings_1.Option("--initial-stake <initialStake>", "Initial stake amount (default: 0)").default('0'))
762
+ .addOption(new extra_typings_1.Option("--registration-expiry <expiry>", "Expiry timestamp (default: now + 12 hours)"))
763
+ .addOption(new extra_typings_1.Option("--pchain-remaining-balance-owner-threshold <threshold>", "P-Chain remaining balance owner threshold").default(1).argParser(cliParser_1.ParserNumber))
764
+ .addOption(new extra_typings_1.Option("--pchain-disable-owner-threshold <threshold>", "P-Chain disable owner threshold").default(1).argParser(cliParser_1.ParserNumber))
765
+ .addOption(new extra_typings_1.Option("--pchain-remaining-balance-owner-address <address>", "P-Chain remaining balance owner address").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserAddress)))
766
+ .addOption(new extra_typings_1.Option("--pchain-disable-owner-address <address>", "P-Chain disable owner address").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserAddress)))
767
+ .asyncAction({ signer: true }, async (config, middlewareAddress, nodeId, blsKey, options) => {
768
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
769
+ const defaultOwnerAddress = (0, viem_1.fromBytes)(avalanchejs_1.utils.bech32ToBytes(config.client.addresses.P), 'hex');
770
+ // Default registration expiry to now + 12 hours if not provided
771
+ // const registrationExpiry = options.registrationExpiry
772
+ // ? BigInt(options.registrationExpiry)
773
+ // : BigInt(Math.floor(Date.now() / 1000) + 12 * 60 * 60); // current time + 12 hours in seconds
774
+ // Build remainingBalanceOwner and disableOwner PChainOwner structs
775
+ // If pchainRemainingBalanceOwnerAddress or pchainDisableOwnerAddress are empty (not provided), use the client account
776
+ const remainingBalanceOwnerAddress = options.pchainRemainingBalanceOwnerAddress.length > 0 ? options.pchainRemainingBalanceOwnerAddress : [defaultOwnerAddress];
777
+ const disableOwnerAddress = options.pchainDisableOwnerAddress.length > 0 ? options.pchainDisableOwnerAddress : [defaultOwnerAddress];
778
+ const remainingBalanceOwner = [
779
+ Number(options.pchainRemainingBalanceOwnerThreshold),
780
+ remainingBalanceOwnerAddress
781
+ ];
782
+ const disableOwner = [
783
+ Number(options.pchainDisableOwnerThreshold),
784
+ disableOwnerAddress
785
+ ];
786
+ const primaryCollateralAddress = await middlewareSvc.read.PRIMARY_ASSET();
787
+ const primaryCollateral = await config.contracts.DefaultCollateral(primaryCollateralAddress);
788
+ const initialStakeWei = (0, viem_1.parseUnits)(options.initialStake.toString(), await primaryCollateral.read.decimals());
789
+ // Call middlewareAddNode
790
+ await (0, middleware_1.middlewareAddNode)(middlewareSvc, nodeId, blsKey, remainingBalanceOwner, disableOwner, initialStakeWei);
791
+ });
792
+ // Complete validator registration
793
+ middlewareCmd
794
+ .command("complete-validator-registration")
795
+ .description("Complete validator registration on the P-Chain and on the middleware after adding a node")
796
+ .addArgument(argMiddlewareAddress)
797
+ .addArgument((0, cliParser_1.ArgHex)("addNodeTxHash", "Add node transaction hash"))
798
+ .addArgument((0, cliParser_1.ArgBLSPOP)())
799
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
800
+ .addOption(new extra_typings_1.Option("--initial-balance <initialBalance>", "Node initial balance to pay for continuous fee").default('0.01')) // In decimals
801
+ .addOption(new extra_typings_1.Option("--skip-wait-api", "Don't wait for the validator to be visible through the P-Chain API"))
802
+ .asyncAction(async (_, middlewareAddress, addNodeTxHash, blsProofOfPossession, options) => {
803
+ const opts = program.opts();
804
+ // If pchainTxPrivateKey is not provided, use the private key
805
+ if (!options.pchainTxPrivateKey) {
806
+ options.pchainTxPrivateKey = opts.privateKey;
807
+ }
808
+ const initialBalance = (0, cliParser_1.ParseUnits)(options.initialBalance, 9, 'Invalid initial balance');
809
+ const client = await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey, opts.safe);
810
+ const config = (0, config_1.getConfig)(client, opts.wait, opts.skipAbiValidation);
811
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
812
+ const balancerSvc = await config.contracts.BalancerValidatorManager(await middlewareSvc.read.balancerValidatorManager());
813
+ // Check if P-Chain address have 0.1 AVAX for tx fees but some times it can be less than 0.000050000 AVAX (perhaps when the validator was removed recently)
814
+ // await requirePChainBallance(config.client, BigInt(Math.round((50000 + Number(initialBalance)))), opts.yes);
815
+ // Call middlewareCompleteValidatorRegistration (no safe for pChain txs)
816
+ await (0, securityModule_1.completeValidatorRegistration)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : client, middlewareSvc, balancerSvc, config, blsProofOfPossession, addNodeTxHash, initialBalance, !options.skipWaitApi);
817
+ });
818
+ // Remove node
819
+ middlewareCmd
820
+ .command("remove-node")
821
+ .description("Remove a node from an L1")
822
+ .addArgument(argMiddlewareAddress)
823
+ .addArgument((0, cliParser_1.ArgNodeID)())
824
+ .asyncAction({ signer: true }, async (config, middlewareAddress, nodeId) => {
825
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
826
+ await (0, middleware_1.middlewareRemoveNode)(middlewareSvc, nodeId);
827
+ });
828
+ // Complete validator removal
829
+ middlewareCmd
830
+ .command("complete-validator-removal")
831
+ .description("Complete validator removal on the P-Chain and on the middleware after removing a node")
832
+ .addArgument(argMiddlewareAddress)
833
+ .addArgument((0, cliParser_1.ArgHex)("removeNodeTxHash", "Remove node transaction hash"))
834
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
835
+ .addOption(new extra_typings_1.Option("--skip-wait-api", "Don't wait for the validator to be visible through the P-Chain API"))
836
+ .addOption(new extra_typings_1.Option("--node-id <nodeId>", "Node ID of the validator being removed").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserNodeID)))
837
+ .addOption(new extra_typings_1.Option("--add-node-tx <addNodeTx>", "Add node transaction hash").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserHex)))
838
+ .asyncAction({ signer: true }, async (config, middlewareAddress, removeNodeTxHash, options) => {
839
+ const opts = program.opts();
840
+ if (!options.pchainTxPrivateKey)
841
+ options.pchainTxPrivateKey = opts.privateKey;
842
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
843
+ const balancerSvc = await config.contracts.BalancerValidatorManager(await middlewareSvc.read.balancerValidatorManager());
844
+ // Check if P-Chain address have 0.01 AVAX for tx fees but some times it can be less than 0.000050000 AVAX (perhaps when the validator was added recently)
845
+ await (0, transferUtils_1.requirePChainBallance)(config.client, 50000n, opts.yes);
846
+ await (0, securityModule_1.completeValidatorRemoval)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : config.client, middlewareSvc, balancerSvc, config, removeNodeTxHash, !options.skipWaitApi, options.nodeId.length > 0 ? options.nodeId : undefined, options.addNodeTx.length > 0 ? options.addNodeTx : undefined);
847
+ });
848
+ // Init stake update
849
+ middlewareCmd
850
+ .command("init-stake-update")
851
+ .description("Initialize validator stake update and lock")
852
+ .addArgument(argMiddlewareAddress)
853
+ .addArgument((0, cliParser_1.ArgNodeID)())
854
+ .argument("newStake", "New stake amount")
855
+ .asyncAction({ signer: true }, async (config, middlewareAddress, nodeId, newStake) => {
856
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
857
+ const primaryCollateral = await middlewareSvc.read.PRIMARY_ASSET();
858
+ const collateral = await config.contracts.DefaultCollateral(primaryCollateral);
859
+ const decimals = await collateral.read.decimals();
860
+ const newStakeWei = (0, viem_1.parseUnits)(newStake, decimals);
861
+ await (0, middleware_1.middlewareInitStakeUpdate)(middlewareSvc, nodeId, newStakeWei);
862
+ });
863
+ // Complete stake update
864
+ middlewareCmd
865
+ .command("complete-stake-update")
866
+ .description("Complete validator stake update of all or specified node IDs")
867
+ .addArgument(argMiddlewareAddress)
868
+ .addArgument((0, cliParser_1.ArgHex)("validatorStakeUpdateTxHash", "Validator stake update transaction hash"))
869
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
870
+ .addOption(new extra_typings_1.Option("--node-id <nodeId>", "Node ID of the validator being removed").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserNodeID)))
871
+ .asyncAction(async (_, middlewareAddress, validatorStakeUpdateTxHash, options) => {
872
+ const opts = program.opts();
873
+ // If pchainTxPrivateKey is not provided, use the private key
874
+ if (!options.pchainTxPrivateKey) {
875
+ options.pchainTxPrivateKey = opts.privateKey;
876
+ }
877
+ const client = await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey, opts.safe);
878
+ const config = (0, config_1.getConfig)(client, opts.wait, opts.skipAbiValidation);
879
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
880
+ // Check if P-Chain address have 0.000050000 AVAX for tx fees
881
+ await (0, transferUtils_1.requirePChainBallance)(client, 50000n, opts.yes);
882
+ await (0, securityModule_1.completeWeightUpdate)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : client, middlewareSvc, config, validatorStakeUpdateTxHash, options.nodeId.length > 0 ? options.nodeId : undefined);
883
+ });
884
+ // Operator cache / calcAndCacheStakes
885
+ middlewareCmd
886
+ .command("calc-operator-cache")
887
+ .description("Calculate and cache stakes for operators")
888
+ .addArgument(argMiddlewareAddress)
889
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch number"))
890
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClass", "Collateral class ID"))
891
+ .asyncAction({ signer: true }, async (config, middlewareAddress, epoch, collateralClass) => {
892
+ logger_1.logger.log("Calculating and caching stakes...");
893
+ if (!config.client.account) {
894
+ throw new Error('Client account is required');
895
+ }
896
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
897
+ const hash = await middlewareSvc.safeWrite.calcAndCacheStakes([epoch, collateralClass], {
898
+ chain: null,
899
+ account: config.client.account,
900
+ });
901
+ logger_1.logger.log("calcAndCacheStakes done, tx hash:", hash);
902
+ });
903
+ // calcAndCacheNodeStakeForAllOperators
904
+ middlewareCmd
905
+ .command("calc-node-stakes")
906
+ .description("Calculate and cache node stakes for all operators")
907
+ .addArgument(argMiddlewareAddress)
908
+ .asyncAction({ signer: true }, async (config, middlewareAddress) => {
909
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
910
+ await (0, middleware_1.middlewareCalcNodeStakes)(middlewareSvc);
911
+ });
912
+ // forceUpdateNodes
913
+ middlewareCmd
914
+ .command("force-update-nodes")
915
+ .description("Force update operator nodes with stake limit")
916
+ .addArgument(argMiddlewareAddress)
917
+ .addArgument(argOperatorAddress)
918
+ .addOption(new extra_typings_1.Option("--limit-stake <stake>", "Stake limit").default(0n).argParser(cliParser_1.ParserAVAX))
919
+ .asyncAction({ signer: true }, async (config, middlewareAddress, operator, options) => {
920
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
921
+ await (0, middleware_1.middlewareForceUpdateNodes)(middlewareSvc, operator, options.limitStake);
922
+ });
923
+ // topUpAllOperatorNodes
924
+ middlewareCmd
925
+ .command("top-up-operator-validators")
926
+ .description("Top up all operator validators to meet a target continuous fee balance")
927
+ .addArgument(argMiddlewareAddress)
928
+ .addArgument(argOperatorAddress)
929
+ .argument("targetBalance", "Target continuous fee balance per validator (in AVAX)")
930
+ .asyncAction({ signer: true }, async (config, middlewareAddress, operator, targetBalance) => {
931
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
932
+ const targetBalanceWei = (0, viem_1.parseUnits)(targetBalance, 9); // AVAX has 9 decimals
933
+ if (targetBalanceWei <= BigInt(1e7)) { // 0.01 AVAX min
934
+ throw new Error("Target balance must be greater than 0.01 AVAX");
935
+ }
936
+ const balancerAddress = await middlewareSvc.read.BALANCER();
937
+ const balancer = await config.contracts.BalancerValidatorManager(balancerAddress);
938
+ const [nodeCount, subnetID] = await Promise.all([middlewareSvc.read.getOperatorNodesLength([operator]), balancer.read.subnetID()]);
939
+ const validators = await (0, pChainUtils_1.getCurrentValidators)(config.client, avalanchejs_1.utils.base58check.encode((0, justification_1.hexToUint8Array)(subnetID)));
940
+ const validatorsToCheck = await Promise.all(ts_belt_1.A.range(0, Number(nodeCount) - 1)
941
+ .map(async (index) => {
942
+ const nodeIdHex = await middlewareSvc.read.operatorNodesArray([operator, BigInt(index)]);
943
+ return validators.find(v => v.nodeID === (0, utils_1.encodeNodeID)(nodeIdHex));
944
+ }));
945
+ const validatorsToTopUp = validatorsToCheck.reduce((acc, validator) => {
946
+ if (validator && validator.balance < targetBalanceWei - BigInt(1e7)) { // 0.01 AVAX min diff
947
+ acc.push({
948
+ validationId: validator.validationID,
949
+ topup: targetBalanceWei - BigInt(validator.balance),
950
+ });
951
+ }
952
+ return acc;
953
+ }, []);
954
+ const totalTopUp = validatorsToTopUp.reduce((acc, v) => acc + v.topup, 0n);
955
+ if (validatorsToTopUp.length === 0) {
956
+ logger_1.logger.log("All operator validators have sufficient balance. No top-up needed.");
957
+ return;
958
+ }
959
+ logger_1.logger.log(`${validatorsToTopUp.length} validators to top-up for a total of ${(0, viem_1.formatUnits)(totalTopUp, 9)} AVAX.`);
960
+ await (0, transferUtils_1.requirePChainBallance)(config.client, totalTopUp + BigInt(2e4) * nodeCount, program.opts().yes); // extra 20000 for fees
961
+ if (!program.opts().yes) {
962
+ const response = await logger_1.logger.prompt(`Proceed with topping up validators? (y/n): `);
963
+ if (response.toLowerCase() !== 'y') {
964
+ logger_1.logger.log("Operation cancelled by user.");
965
+ process.exit(0);
966
+ }
967
+ }
968
+ for (const { validationId, topup } of validatorsToTopUp) {
969
+ logger_1.logger.log(`\nTopping up validator ${validationId}`);
970
+ const amount = Number(topup) / 1e9;
971
+ (0, ts_belt_1.pipe)(await (0, pChainUtils_1.increasePChainValidatorBalance)(config.client, amount, validationId, false), ts_belt_1.R.tapError(err => { logger_1.logger.error(err); process.exit(1); }));
972
+ }
973
+ logger_1.logger.log("\nCompleted top-up of operator validators.");
974
+ logger_1.logger.addData('total_amount', totalTopUp);
975
+ logger_1.logger.addData('validators', validatorsToTopUp);
976
+ });
977
+ // getOperatorStake (read)
978
+ middlewareCmd
979
+ .command("get-operator-stake")
980
+ .description("Get operator stake for a specific epoch and collateral class")
981
+ .addArgument(argMiddlewareAddress)
982
+ .addArgument(argOperatorAddress)
983
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch number"))
984
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClass", "Collateral class ID"))
985
+ .asyncAction(async (config, middlewareAddress, operator, epoch, collateralClass) => {
986
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
987
+ await (0, middleware_1.middlewareGetOperatorStake)(middlewareSvc, operator, epoch, collateralClass);
988
+ });
989
+ middlewareCmd
990
+ .command("get-operator-nodes")
991
+ .description("Get operator nodes")
992
+ .addArgument(argMiddlewareAddress)
993
+ .addArgument(argOperatorAddress)
994
+ .asyncAction(async (config, middlewareAddress, operator) => {
995
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
996
+ const nodeCount = await middlewareSvc.read.getOperatorNodesLength([operator]);
997
+ const abi = [(0, viem_1.getAbiItem)({ abi: middlewareSvc.abi, name: 'operatorNodesArray' })];
998
+ const multicallResult = await config.client.multicall({
999
+ contracts: ts_belt_1.A.range(0, Number(nodeCount) - 1).map(i => { return { args: [operator, BigInt(i)], abi, address: middlewareAddress, functionName: 'operatorNodesArray' }; })
1000
+ });
1001
+ const nodes = multicallResult.map((node) => node.error ? "error" : (0, utils_1.encodeNodeID)(node.result));
1002
+ logger_1.logger.log(nodes);
1003
+ logger_1.logger.addData('nodes', nodes);
1004
+ });
1005
+ // getCurrentEpoch (read)
1006
+ middlewareCmd
1007
+ .command("get-current-epoch")
1008
+ .description("Get current epoch number")
1009
+ .addArgument(argMiddlewareAddress)
1010
+ .asyncAction(async (config, middlewareAddress) => {
1011
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1012
+ await (0, middleware_1.middlewareGetCurrentEpoch)(middlewareSvc);
1013
+ });
1014
+ // getEpochStartTs (read)
1015
+ middlewareCmd
1016
+ .command("get-epoch-start-ts")
1017
+ .description("Get epoch start timestamp")
1018
+ .addArgument(argMiddlewareAddress)
1019
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch number"))
1020
+ .asyncAction(async (config, middlewareAddress, epoch) => {
1021
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1022
+ await (0, middleware_1.middlewareGetEpochStartTs)(middlewareSvc, epoch);
1023
+ });
1024
+ // getActiveNodesForEpoch (read)
1025
+ middlewareCmd
1026
+ .command("get-active-nodes-for-epoch")
1027
+ .description("Get active nodes for an operator in a specific epoch")
1028
+ .addArgument(argMiddlewareAddress)
1029
+ .addArgument(argOperatorAddress)
1030
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch number"))
1031
+ .asyncAction(async (config, middlewareAddress, operator, epoch) => {
1032
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1033
+ await (0, middleware_1.middlewareGetActiveNodesForEpoch)(middlewareSvc, operator, epoch);
1034
+ });
1035
+ // getOperatorNodesLength (read)
1036
+ middlewareCmd
1037
+ .command("get-operator-nodes-length")
1038
+ .description("Get current number of nodes for an operator")
1039
+ .addArgument(argMiddlewareAddress)
1040
+ .addArgument(argOperatorAddress)
1041
+ .asyncAction(async (config, middlewareAddress, operator) => {
1042
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1043
+ await (0, middleware_1.middlewareGetOperatorNodesLength)(middlewareSvc, operator);
1044
+ });
1045
+ // getNodeStakeCache (read)
1046
+ middlewareCmd
1047
+ .command("get-node-stake-cache")
1048
+ .description("Get node stake cache for a specific epoch and validator")
1049
+ .addArgument(argMiddlewareAddress)
1050
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch number"))
1051
+ .addArgument((0, cliParser_1.ArgHex)("validationId", "Validation ID"))
1052
+ .asyncAction(async (config, middlewareAddress, epoch, validationId) => {
1053
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1054
+ await (0, middleware_1.middlewareGetNodeStakeCache)(middlewareSvc, epoch, validationId);
1055
+ });
1056
+ // getOperatorLockedStake (read)
1057
+ middlewareCmd
1058
+ .command("get-operator-locked-stake")
1059
+ .description("Get operator locked stake")
1060
+ .addArgument(argMiddlewareAddress)
1061
+ .addArgument(argOperatorAddress)
1062
+ .asyncAction(async (config, middlewareAddress, operator) => {
1063
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1064
+ await (0, middleware_1.middlewareGetOperatorLockedStake)(middlewareSvc, operator);
1065
+ });
1066
+ // nodePendingRemoval (read)
1067
+ middlewareCmd
1068
+ .command("node-pending-removal")
1069
+ .description("Check if node is pending removal")
1070
+ .addArgument(argMiddlewareAddress)
1071
+ .addArgument((0, cliParser_1.ArgHex)("validationId", "Validation ID"))
1072
+ .asyncAction(async (config, middlewareAddress, validationId) => {
1073
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1074
+ await (0, middleware_1.middlewareNodePendingRemoval)(middlewareSvc, validationId);
1075
+ });
1076
+ // getOperatorUsedStakeCached (read)
1077
+ middlewareCmd
1078
+ .command("get-operator-used-stake")
1079
+ .description("Get operator used stake from cache")
1080
+ .addArgument(argMiddlewareAddress)
1081
+ .addArgument(argOperatorAddress)
1082
+ .asyncAction(async (config, middlewareAddress, operator) => {
1083
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1084
+ await (0, middleware_1.middlewareGetOperatorUsedStake)(middlewareSvc, operator);
1085
+ });
1086
+ // getOperatorAvailableStake (read)
1087
+ middlewareCmd
1088
+ .command("get-operator-available-stake")
1089
+ .description("Get operator available stake")
1090
+ .addArgument(argMiddlewareAddress)
1091
+ .addArgument(argOperatorAddress)
1092
+ .asyncAction(async (config, middlewareAddress, operator) => {
1093
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1094
+ const availableStake = await middlewareSvc.read.getOperatorAvailableStake([operator]);
1095
+ logger_1.logger.log(`Operator ${operator} available stake: ${availableStake}`);
1096
+ });
1097
+ // getAllOperators (read)
1098
+ middlewareCmd
1099
+ .command("get-all-operators")
1100
+ .description("Get all operators registered")
1101
+ .addArgument(argMiddlewareAddress)
1102
+ .asyncAction(async (config, middlewareAddress) => {
1103
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1104
+ await (0, middleware_1.middlewareGetAllOperators)(middlewareSvc);
1105
+ });
1106
+ // getCollateralClassIds (read)
1107
+ middlewareCmd
1108
+ .command("get-collateral-class-ids")
1109
+ .description("Get all collateral class IDs from the middleware")
1110
+ .addArgument(argMiddlewareAddress)
1111
+ .asyncAction(async (config, middlewareAddress) => {
1112
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1113
+ await (0, middleware_1.getCollateralClassIds)(middlewareSvc);
1114
+ });
1115
+ // getActiveCollateralClasses (read)
1116
+ middlewareCmd
1117
+ .command("get-active-collateral-classes")
1118
+ .description("Get active collateral classes (primary and secondary)")
1119
+ .addArgument(argMiddlewareAddress)
1120
+ .asyncAction(async (config, middlewareAddress) => {
1121
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1122
+ await (0, middleware_1.getActiveCollateralClasses)(middlewareSvc);
1123
+ });
1124
+ middlewareCmd
1125
+ .command("node-logs")
1126
+ .description("Get middleware node logs")
1127
+ .addArgument(argMiddlewareAddress)
1128
+ .addOption(new extra_typings_1.Option("--node-id <nodeId>", "Node ID to filter logs").default(undefined).argParser(cliParser_1.ParserNodeID))
1129
+ .addOption(new extra_typings_1.Option('--snowscan-api-key <string>', "Snowscan API key").default(""))
1130
+ .asyncAction(async (config, middlewareAddress, options) => {
1131
+ logger_1.logger.log(`nodeId: ${options.nodeId}`);
1132
+ const middleware = await config.contracts.L1Middleware(middlewareAddress);
1133
+ await (0, middleware_1.middlewareGetNodeLogs)(config.client, middleware, config, options.nodeId, options.snowscanApiKey);
1134
+ });
1135
+ middlewareCmd
1136
+ .command("get-last-node-validation-id")
1137
+ .description("Set middleware log level")
1138
+ .addArgument(argMiddlewareAddress)
1139
+ .addArgument((0, cliParser_1.ArgNodeID)())
1140
+ .asyncAction(async (config, middlewareAddress, nodeId) => {
1141
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1142
+ const balancerAddress = await middlewareSvc.read.balancerValidatorManager();
1143
+ const balancerSvc = await config.contracts.BalancerValidatorManager(balancerAddress);
1144
+ logger_1.logger.log(`Fetching last validation ID`);
1145
+ const validationId = await (0, middleware_1.middlewareLastValidationId)(config.client, middlewareSvc, balancerSvc, nodeId);
1146
+ logger_1.logger.log(`Last validationID: ${validationId}`);
1147
+ });
1148
+ middlewareCmd
1149
+ .command("to-vault-epoch")
1150
+ .description("convert middleware epoch to a vault epoch")
1151
+ .addArgument(argMiddlewareAddress)
1152
+ .addArgument(argVaultAddress)
1153
+ .addArgument((0, cliParser_1.ArgNumber)("middlewareEpoch", "Middleware epoch number"))
1154
+ .asyncAction(async (config, middlewareAddress, vaultAddress, middlewareEpoch) => {
1155
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1156
+ const vaultSvc = await config.contracts.VaultTokenized(vaultAddress);
1157
+ const middlewareEpochTs = await middlewareSvc.read.getEpochStartTs([middlewareEpoch]);
1158
+ const vaultEpoch = await vaultSvc.read.epochAt([middlewareEpochTs]);
1159
+ logger_1.logger.log(`Vault epoch at middleware epoch ${middlewareEpoch} (timestamp: ${middlewareEpochTs}) is ${vaultEpoch}`);
1160
+ });
1161
+ middlewareCmd
1162
+ .command("update-window-ends-ts")
1163
+ .description("Get the end timestamp of the last completed middleware epoch window")
1164
+ .addArgument(argMiddlewareAddress)
1165
+ .asyncAction(async (config, middlewareAddress) => {
1166
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1167
+ const [currentEpoch, updateWindow] = await middlewareSvc.multicall(['getCurrentEpoch', 'UPDATE_WINDOW']);
1168
+ const lastEpochStartTs = await middlewareSvc.read.getEpochStartTs([currentEpoch]);
1169
+ logger_1.logger.log(`Window ends at: ${lastEpochStartTs + updateWindow}`);
1170
+ });
1171
+ middlewareCmd
1172
+ .command("vault-to-middleware-epoch")
1173
+ .description("convert vault epoch to a middleware epoch")
1174
+ .addArgument(argMiddlewareAddress)
1175
+ .addArgument(argVaultAddress)
1176
+ .addArgument((0, cliParser_1.ArgNumber)("vaultEpoch", "Vault epoch number"))
1177
+ .asyncAction(async (config, middlewareAddress, vaultAddress, vaultEpoch) => {
1178
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1179
+ const vaultSvc = await config.contracts.VaultTokenized(vaultAddress);
1180
+ const vaultEpochStartTs = await vaultSvc.read.epochDuration() * vaultEpoch + await vaultSvc.read.epochDurationInit();
1181
+ const middlewareEpoch = await middlewareSvc.read.getEpochAtTs([vaultEpochStartTs]);
1182
+ logger_1.logger.log(`Middleware epoch at vault epoch ${vaultEpoch} (timestamp: ${vaultEpochStartTs}) is ${middlewareEpoch}`);
1183
+ });
1184
+ middlewareCmd
1185
+ .command("set-vault-manager")
1186
+ .description("Set vault manager")
1187
+ .addArgument(argMiddlewareAddress)
1188
+ .addArgument(argMiddlewareVaultManagerAddress)
1189
+ .asyncAction({ signer: true }, async (config, middlewareAddress, vaultManagerAddress) => {
1190
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1191
+ await middlewareSvc.safeWrite.setVaultManager([vaultManagerAddress]);
1192
+ logger_1.logger.log(`Set vault manager to ${vaultManagerAddress} on middleware ${middlewareAddress} ok`);
1193
+ });
1194
+ middlewareCmd
1195
+ .command("get-operator-validation-ids")
1196
+ .description("Get operator validation IDs")
1197
+ .addArgument(argMiddlewareAddress)
1198
+ .addArgument(argOperatorAddress)
1199
+ .asyncAction(async (config, middlewareAddress, operator) => {
1200
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1201
+ const validationIDs = await middlewareSvc.read.getOperatorValidationIDs([operator]);
1202
+ logger_1.logger.log(`Validation IDs for operator ${operator}: ${validationIDs.join(', ')}`);
1203
+ });
1204
+ middlewareCmd
1205
+ .command("account-info")
1206
+ .description("Get account info")
1207
+ .addArgument(argMiddlewareAddress)
1208
+ .addArgument((0, cliParser_1.ArgAddress)("account", "Account address"))
1209
+ .asyncAction(async (config, middlewareAddress, account) => {
1210
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1211
+ const [owner, operators, epoch, balancerAddress] = await middlewareSvc.multicall(['owner', 'getAllOperators', 'getCurrentEpoch', 'BALANCER']);
1212
+ const roles = (0, accessControl_1.getRoles)(middlewareSvc);
1213
+ const accessControl = await config.contracts.AccessControl(middlewareAddress);
1214
+ const hasRole = await accessControl.multicall(roles.map(role => { return { name: 'hasRole', args: [(0, accessControl_1.ensureRoleHex)(role), account] }; }));
1215
+ logger_1.logger.log(`Account ${account} has the following rights: `);
1216
+ if (account === owner) {
1217
+ logger_1.logger.log(`L1 owner`);
1218
+ }
1219
+ if (hasRole.some(role => role)) {
1220
+ logger_1.logger.log(`Middleware roles: `);
1221
+ logger_1.logger.log(" " + roles.filter((_, index) => hasRole[index]).join('\n '));
1222
+ }
1223
+ if (operators.includes(account)) {
1224
+ const balancerSvc = await config.contracts.BalancerValidatorManager(balancerAddress);
1225
+ const [stake, validationIDs] = await middlewareSvc.multicall([
1226
+ { name: 'getOperatorStake', args: [account, 1, BigInt(epoch)] },
1227
+ { name: 'getOperatorValidationIDs', args: [account] }
1228
+ ]);
1229
+ const validators = await balancerSvc.multicall(validationIDs.flatMap(id => { return [{ name: 'getValidator', args: [id] }, { name: 'isValidatorPendingWeightUpdate', args: [id] }]; }));
1230
+ logger_1.logger.log(`Operator with stake ${stake} and the following validators: `);
1231
+ const subnetIdHex = await balancerSvc.read.subnetID();
1232
+ const pChainValidators = await (0, pChainUtils_1.getCurrentValidators)(config.client, avalanchejs_1.utils.base58check.encode((0, viem_1.hexToBytes)(subnetIdHex)));
1233
+ const formated = {};
1234
+ for (let i = 0; i < validators.length; i += 2) {
1235
+ const validator = validators[i];
1236
+ const pendingWeightUpdate = validators[i + 1];
1237
+ const status = balancer_1.ValidatorStatusNames[validator.status == balancer_1.ValidatorStatus.Active && pendingWeightUpdate ? balancer_1.ValidatorStatus.PendingStakeUpdated : validator.status];
1238
+ const pChainValidator = pChainValidators.find(v => v.nodeID === validator.nodeID);
1239
+ formated[(0, utils_1.encodeNodeID)(validator.nodeID)] = { NodeID: (0, utils_1.encodeNodeID)(validator.nodeID), status, weight: validator.weight, ValidationId: validationIDs[i / 2], continuousAVAXBalance: (0, viem_1.parseUnits)(pChainValidator?.balance?.toString() ?? '0', 9) };
1240
+ }
1241
+ logger_1.logger.logJsonTree(formated);
1242
+ }
1243
+ });
1244
+ middlewareCmd
1245
+ .command("info")
1246
+ .description("Get general information about the middleware")
1247
+ .addArgument(argMiddlewareAddress)
1248
+ .asyncAction(async (config, middlewareAddress) => {
1249
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
1250
+ await (0, middleware_1.middlewareInfo)(middlewareSvc);
1251
+ });
1252
+ middlewareCmd
1253
+ .command('weight-sync')
1254
+ .description('Watch for operators weight changes')
1255
+ .addArgument(argMiddlewareAddress)
1256
+ .addOption(new extra_typings_1.Option('-e, --epochs <number>', 'Number of epochs to watch').argParser(Number))
1257
+ .addOption(new extra_typings_1.Option('-l, --loop-epochs <number>', 'Number of epochs to loop').argParser(Number))
1258
+ .asyncAction({ signer: true }, async (config, middlewareAddress, options) => {
1259
+ await (0, middleware_1.weightSync)(await config.contracts.L1Middleware(middlewareAddress), config, { epochs: options.epochs, loopEpochs: options.loopEpochs });
1260
+ });
1261
+ /**
1262
+ * --------------------------------------------------
1263
+ * OPERATOR → L1: optIn / optOut / check
1264
+ * --------------------------------------------------
1265
+ */
1266
+ const operatorOptInCmd = program
1267
+ .command("opt-in")
1268
+ .description("Commands for operator opt-in services");
1269
+ operatorOptInCmd
1270
+ .command("l1-in")
1271
+ .description("Operator opts in to a given L1")
1272
+ .addArgument(argValidatorManagerAddress)
1273
+ .asyncAction({ signer: true }, async (config, l1Address) => {
1274
+ const service = await config.contracts.OperatorL1OptInService();
1275
+ await (0, operatorOptIn_1.optInL1)(service, l1Address);
1276
+ });
1277
+ operatorOptInCmd
1278
+ .command("l1-out")
1279
+ .description("Operator opts out from a given L1")
1280
+ .addArgument(argValidatorManagerAddress)
1281
+ .asyncAction({ signer: true }, async (config, l1Address) => {
1282
+ const service = await config.contracts.OperatorL1OptInService();
1283
+ await (0, operatorOptIn_1.optOutL1)(service, l1Address);
1284
+ });
1285
+ operatorOptInCmd
1286
+ .command("check-l1")
1287
+ .description("Check if an operator is opted in to a given L1")
1288
+ .addArgument(argOperatorAddress)
1289
+ .addArgument(argValidatorManagerAddress)
1290
+ .asyncAction(async (config, operator, l1Address) => {
1291
+ const service = await config.contracts.OperatorL1OptInService();
1292
+ await (0, operatorOptIn_1.checkOptInL1)(service, operator, l1Address);
1293
+ });
1294
+ /**
1295
+ * --------------------------------------------------
1296
+ * OPERATOR → Vault: optIn / optOut / check
1297
+ * --------------------------------------------------
1298
+ */
1299
+ operatorOptInCmd
1300
+ .command("vault-in")
1301
+ .description("Operator opts in to a given Vault")
1302
+ .addArgument(argVaultAddress)
1303
+ .asyncAction({ signer: true }, async (config, vaultAddress) => {
1304
+ const service = await config.contracts.OperatorVaultOptInService();
1305
+ await (0, operatorOptIn_1.optInVault)(service, vaultAddress);
1306
+ });
1307
+ operatorOptInCmd
1308
+ .command("vault-out")
1309
+ .description("Operator opts out from a given Vault")
1310
+ .addArgument(argVaultAddress)
1311
+ .asyncAction({ signer: true }, async (config, vaultAddress) => {
1312
+ const service = await config.contracts.OperatorVaultOptInService();
1313
+ await (0, operatorOptIn_1.optOutVault)(service, vaultAddress);
1314
+ });
1315
+ operatorOptInCmd
1316
+ .command("check-vault")
1317
+ .description("Check if an operator is opted in to a given Vault")
1318
+ .addArgument(argOperatorAddress)
1319
+ .addArgument(argVaultAddress)
1320
+ .asyncAction(async (config, operator, vaultAddress) => {
1321
+ const service = await config.contracts.OperatorVaultOptInService();
1322
+ await (0, operatorOptIn_1.checkOptInVault)(service, operator, vaultAddress);
1323
+ });
1324
+ /**
1325
+ * --------------------------------------------------
1326
+ * Validator Manager
1327
+ * --------------------------------------------------
1328
+ */
1329
+ const validatorManagerCmd = program
1330
+ .command("vmc")
1331
+ .description("Commands to interact with ValidatorManager contracts");
1332
+ validatorManagerCmd
1333
+ .command("info")
1334
+ .description("Get summary informations of a ValidatorManager contract")
1335
+ .addArgument(argValidatorManagerAddress)
1336
+ .asyncAction(async (config, validatorManagerAddress) => {
1337
+ // instantiate ValidatorManager contract
1338
+ const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress);
1339
+ const results = await validatorManager.multicall([
1340
+ 'getChurnTracker',
1341
+ 'getChurnPeriodSeconds',
1342
+ 'l1TotalWeight',
1343
+ 'owner',
1344
+ 'subnetID'
1345
+ ], { details: true });
1346
+ logger_1.logger.log(results.reduce((acc, r) => ({ ...acc, [r.name]: r.result }), {}));
1347
+ });
1348
+ validatorManagerCmd
1349
+ .command("transfer-ownership")
1350
+ .description("Transfer the ownership of a ValidatorManager contract")
1351
+ .addArgument(argValidatorManagerAddress)
1352
+ .addArgument((0, cliParser_1.ArgAddress)("owner", "Owner address"))
1353
+ .asyncAction({ signer: true }, async (config, validatorManagerAddress, owner) => {
1354
+ // instantiate ValidatorManager contract
1355
+ const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress);
1356
+ await validatorManager.safeWrite.transferOwnership([owner]);
1357
+ });
1358
+ validatorManagerCmd
1359
+ .command("complete-validator-removal")
1360
+ .description("Complete the removal of a validator that has been pending removal")
1361
+ .addArgument(argValidatorManagerAddress)
1362
+ .addArgument((0, cliParser_1.ArgHex)("removalTxId", "Removal transaction ID"))
1363
+ .asyncAction({ signer: true }, async (config, validatorManagerAddress, removalTxId) => {
1364
+ // instantiate ValidatorManager contract
1365
+ const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress);
1366
+ logger_1.logger.error("Not implemented yet");
1367
+ });
1368
+ /**
1369
+ * --------------------------------------------------
1370
+ * BALANCER
1371
+ * --------------------------------------------------
1372
+ */
1373
+ const balancerCmd = program
1374
+ .command("balancer")
1375
+ .description("Commands to interact with BalancerValidatorManager contracts");
1376
+ balancerCmd
1377
+ .command("set-up-security-module")
1378
+ .description("Set up a security module")
1379
+ .addArgument(argBalancerAddress)
1380
+ .addArgument(argMiddlewareAddress)
1381
+ .addArgument((0, cliParser_1.ArgBigInt)("maxWeight", "Maximum weight"))
1382
+ .asyncAction({ signer: true }, async (config, balancerValidatorManagerAddress, middlewareAddress, maxWeight) => {
1383
+ // instantiate BalancerValidatorManager contract
1384
+ const balancer = await config.contracts.BalancerValidatorManager(balancerValidatorManagerAddress);
1385
+ await (0, balancer_1.setUpSecurityModule)(balancer, middlewareAddress, maxWeight);
1386
+ });
1387
+ balancerCmd
1388
+ .command("get-security-modules")
1389
+ .description("Get all security modules")
1390
+ .addArgument(argBalancerAddress)
1391
+ .asyncAction(async (config, balancerValidatorManagerAddress) => {
1392
+ const balancer = await config.contracts.BalancerValidatorManager(balancerValidatorManagerAddress);
1393
+ await (0, balancer_1.getSecurityModules)(balancer);
1394
+ });
1395
+ balancerCmd
1396
+ .command("get-security-module-weights")
1397
+ .description("Get security module weights")
1398
+ .addArgument(argBalancerAddress)
1399
+ .addArgument((0, cliParser_1.ArgAddress)("securityModule", "Security module address"))
1400
+ .asyncAction(async (config, balancerValidatorManagerAddress, securityModule) => {
1401
+ const balancer = await config.contracts.BalancerValidatorManager(balancerValidatorManagerAddress);
1402
+ await (0, balancer_1.getSecurityModuleWeights)(balancer, securityModule);
1403
+ });
1404
+ balancerCmd
1405
+ .command("get-validator-status")
1406
+ .description("Get validator status by node ID")
1407
+ .addArgument(argBalancerAddress)
1408
+ .addArgument((0, cliParser_1.ArgNodeID)("nodeId", "Node ID"))
1409
+ .asyncAction(async (config, balancerAddress, nodeId) => {
1410
+ const balancer = await config.contracts.BalancerValidatorManager(balancerAddress);
1411
+ const validationId = await balancer.read.getNodeValidationID([(0, utils_1.parseNodeID)(nodeId, false)]);
1412
+ if (Number(validationId) === 0) {
1413
+ logger_1.logger.log("Validator status: NotRegistered");
1414
+ return;
1415
+ }
1416
+ const [validator, PendingWeightUpdate] = await Promise.all([balancer.read.getValidator([validationId]), balancer.read.isValidatorPendingWeightUpdate([validationId])]);
1417
+ const status = validator.status == balancer_1.ValidatorStatus.Active && PendingWeightUpdate ? balancer_1.ValidatorStatus.PendingStakeUpdated : validator.status;
1418
+ logger_1.logger.log("Validator status:", balancer_1.ValidatorStatusNames[status]);
1419
+ logger_1.logger.addData("status", balancer_1.ValidatorStatusNames[status]);
1420
+ logger_1.logger.addData("statusId", status);
1421
+ logger_1.logger.addData("validationId", validationId);
1422
+ logger_1.logger.addData("nodeId", nodeId);
1423
+ });
1424
+ balancerCmd
1425
+ .command("resend-validator-registration")
1426
+ .description("Resend validator registration transaction")
1427
+ .addArgument(argBalancerAddress)
1428
+ .addArgument((0, cliParser_1.ArgNodeID)("nodeId", "Node ID"))
1429
+ .asyncAction({ signer: true }, async (config, balancerAddress, nodeId) => {
1430
+ const balancer = await config.contracts.BalancerValidatorManager(balancerAddress);
1431
+ const nodeIdHex32 = (0, utils_1.parseNodeID)(nodeId, false);
1432
+ const validationId = await balancer.read.getNodeValidationID([nodeIdHex32]);
1433
+ const hash = await balancer.safeWrite.resendRegisterValidatorMessage([validationId]);
1434
+ logger_1.logger.log("resendValidatorRegistration executed successfully, tx hash:", hash);
1435
+ });
1436
+ balancerCmd
1437
+ .command("resend-weight-update")
1438
+ .description("Resend validator weight update transaction")
1439
+ .addArgument(argBalancerAddress)
1440
+ .addArgument((0, cliParser_1.ArgNodeID)("nodeId", "Node ID"))
1441
+ .asyncAction({ signer: true }, async (config, balancerAddress, nodeId) => {
1442
+ const balancer = await config.contracts.BalancerValidatorManager(balancerAddress);
1443
+ const nodeIdHex32 = (0, utils_1.parseNodeID)(nodeId, false);
1444
+ const validationId = await balancer.read.getNodeValidationID([nodeIdHex32]);
1445
+ const hash = await balancer.safeWrite.resendValidatorWeightUpdate([validationId]);
1446
+ logger_1.logger.log("resendWeightUpdate executed successfully, tx hash:", hash);
1447
+ });
1448
+ balancerCmd
1449
+ .command("resend-validator-removal")
1450
+ .description("Resend validator removal transaction")
1451
+ .addArgument(argBalancerAddress)
1452
+ .addArgument((0, cliParser_1.ArgNodeID)("nodeId", "Node ID"))
1453
+ .asyncAction({ signer: true }, async (config, balancerAddress, nodeId) => {
1454
+ const balancer = await config.contracts.BalancerValidatorManager(balancerAddress);
1455
+ const nodeIdHex32 = (0, utils_1.parseNodeID)(nodeId, false);
1456
+ const validationId = await balancer.read.getNodeValidationID([nodeIdHex32]);
1457
+ const hash = await balancer.safeWrite.resendValidatorRemovalMessage([validationId]);
1458
+ logger_1.logger.log("resendValidatorRemoval executed successfully, tx hash:", hash);
1459
+ });
1460
+ balancerCmd
1461
+ .command("transfer-l1-ownership")
1462
+ .description("Transfer Validator manager, balancer and its security modules ownership to a new owner")
1463
+ .addArgument(argBalancerAddress)
1464
+ .addArgument((0, cliParser_1.ArgAddress)("newOwner", "New owner address"))
1465
+ .asyncAction({ signer: true }, async (config, balancerAddress, newOwner) => {
1466
+ const balancer = await config.contracts.BalancerValidatorManager(balancerAddress);
1467
+ const VMTx = await balancer.safeWrite.transferValidatorManagerOwnership([newOwner]);
1468
+ logger_1.logger.log("transferValidatorManagerOwnership executed successfully, tx hash:", VMTx);
1469
+ const BTx = await balancer.safeWrite.transferOwnership([newOwner]);
1470
+ logger_1.logger.log("transferOwnership of balancer executed successfully, tx hash:", BTx);
1471
+ const securityModules = await balancer.read.getSecurityModules();
1472
+ for (const smAddress of securityModules) {
1473
+ const smOwnable = await config.contracts.Ownable(smAddress);
1474
+ const SMTx = await smOwnable.safeWrite.transferOwnership([newOwner]);
1475
+ logger_1.logger.log(`transferOwnership of security module ${smAddress} executed successfully, tx hash:`, SMTx);
1476
+ const smAccessControl = await config.contracts.AccessControl(smAddress);
1477
+ const isAccessControl = await smAccessControl.read.supportsInterface(["0x7965db0b"]);
1478
+ if (isAccessControl) {
1479
+ const ROLETX = await smAccessControl.safeWrite.grantRole([await smAccessControl.read.DEFAULT_ADMIN_ROLE(), newOwner]);
1480
+ logger_1.logger.log(`grantRole DEFAULT_ADMIN_ROLE to ${newOwner} on security module ${smAddress} executed successfully, tx hash:`, ROLETX);
1481
+ }
1482
+ }
1483
+ });
1484
+ /**
1485
+ * --------------------------------------------------
1486
+ * POA-Security-Module
1487
+ * --------------------------------------------------
1488
+ * This section is for the POA Security Module commands.
1489
+ * It includes commands to add or remove validators
1490
+ */
1491
+ const poaCmd = program
1492
+ .command("poa")
1493
+ .description("Commands to interact with POA Security Module contracts");
1494
+ poaCmd
1495
+ .command("add-node")
1496
+ .description("Add a new node to an L1")
1497
+ .addArgument(argPoaSecurityModuleAddress)
1498
+ .addArgument((0, cliParser_1.ArgNodeID)())
1499
+ .addArgument((0, cliParser_1.ArgHex)("blsKey", "BLS public key"))
1500
+ .addArgument((0, cliParser_1.ArgBigInt)("initialWeight", "Initial weight of the validator"))
1501
+ .addOption(new extra_typings_1.Option("--registration-expiry <expiry>", "Expiry timestamp (default: now + 12 hours)"))
1502
+ .addOption(new extra_typings_1.Option("--pchain-remaining-balance-owner-threshold <threshold>", "P-Chain remaining balance owner threshold").default(1).argParser(cliParser_1.ParserNumber))
1503
+ .addOption(new extra_typings_1.Option("--pchain-disable-owner-threshold <threshold>", "P-Chain disable owner threshold").default(1).argParser(cliParser_1.ParserNumber))
1504
+ .addOption(new extra_typings_1.Option("--pchain-remaining-balance-owner-address <address>", "P-Chain remaining balance owner address").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserAddress)))
1505
+ .addOption(new extra_typings_1.Option("--pchain-disable-owner-address <address>", "P-Chain disable owner address").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserAddress)))
1506
+ .asyncAction({ signer: true }, async (config, poaSecurityModule, nodeId, blsKey, initialWeight, options) => {
1507
+ const poaSM = await config.contracts.PoASecurityModule(poaSecurityModule);
1508
+ const defaultOwnerAddress = (0, viem_1.fromBytes)(avalanchejs_1.utils.bech32ToBytes(config.client.addresses.P), 'hex');
1509
+ // Default registration expiry to now + 12 hours if not provided
1510
+ // const registrationExpiry = options.registrationExpiry
1511
+ // ? BigInt(options.registrationExpiry)
1512
+ // : BigInt(Math.floor(Date.now() / 1000) + 12 * 60 * 60); // current time + 12 hours in seconds
1513
+ // Build remainingBalanceOwner and disableOwner PChainOwner structs
1514
+ // If pchainRemainingBalanceOwnerAddress or pchainDisableOwnerAddress are empty (not provided), use the client account
1515
+ const remainingBalanceOwnerAddress = options.pchainRemainingBalanceOwnerAddress.length > 0 ? options.pchainRemainingBalanceOwnerAddress : [defaultOwnerAddress];
1516
+ const disableOwnerAddress = options.pchainDisableOwnerAddress.length > 0 ? options.pchainDisableOwnerAddress : [defaultOwnerAddress];
1517
+ const remainingBalanceOwner = [
1518
+ Number(options.pchainRemainingBalanceOwnerThreshold),
1519
+ remainingBalanceOwnerAddress
1520
+ ];
1521
+ const disableOwner = [
1522
+ Number(options.pchainDisableOwnerThreshold),
1523
+ disableOwnerAddress
1524
+ ];
1525
+ const nodeIdHex32 = (0, utils_1.parseNodeID)(nodeId, false);
1526
+ const hash = await poaSM.safeWrite.initiateValidatorRegistration([nodeIdHex32, blsKey, { threshold: remainingBalanceOwner[0], addresses: remainingBalanceOwner[1] }, { threshold: disableOwner[0], addresses: disableOwner[1] }, initialWeight]);
1527
+ logger_1.logger.log("addNode executed successfully, tx hash:", hash);
1528
+ });
1529
+ poaCmd
1530
+ .command("complete-validator-registration")
1531
+ .description("Complete validator registration on the P-Chain and on the middleware after adding a node")
1532
+ .addArgument(argPoaSecurityModuleAddress)
1533
+ .addArgument((0, cliParser_1.ArgHex)("addNodeTxHash", "Add node transaction hash"))
1534
+ .addArgument((0, cliParser_1.ArgBLSPOP)())
1535
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
1536
+ .addOption(new extra_typings_1.Option("--initial-balance <initialBalance>", "Node initial balance to pay for continuous fee").default('0.01'))
1537
+ .addOption(new extra_typings_1.Option("--skip-wait-api", "Don't wait for the validator to be visible through the P-Chain API"))
1538
+ .asyncAction({ signer: true }, async (config, poaSecurityModuleAddress, addNodeTxHash, blsProofOfPossession, options) => {
1539
+ const opts = program.opts();
1540
+ // If pchainTxPrivateKey is not provided, use the private key
1541
+ if (!options.pchainTxPrivateKey) {
1542
+ options.pchainTxPrivateKey = opts.privateKey;
1543
+ }
1544
+ const poaSecurityModule = await config.contracts.PoASecurityModule(poaSecurityModuleAddress);
1545
+ const balancerSvc = await config.contracts.BalancerValidatorManager(await poaSecurityModule.read.balancerValidatorManager());
1546
+ const initialBalance = (0, cliParser_1.ParseUnits)(options.initialBalance, 9, 'Invalid initial balance');
1547
+ // Check if P-Chain address have 0.1 AVAX for tx fees but some times it can be less than 0.000050000 AVAX (perhaps when the validator was removed recently)
1548
+ await (0, transferUtils_1.requirePChainBallance)(config.client, BigInt(Math.round((50000 + Number(initialBalance)))), opts.yes);
1549
+ // Call middlewareCompleteValidatorRegistration
1550
+ await (0, securityModule_1.completeValidatorRegistration)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : config.client, poaSecurityModule, balancerSvc, config, blsProofOfPossession, addNodeTxHash, initialBalance, !options.skipWaitApi);
1551
+ });
1552
+ poaCmd
1553
+ .command("remove-node")
1554
+ .description("Initiate validator removal")
1555
+ .addArgument(argPoaSecurityModuleAddress)
1556
+ .addArgument((0, cliParser_1.ArgNodeID)())
1557
+ .asyncAction({ signer: true }, async (config, poaSecurityModuleAddress, nodeID) => {
1558
+ const poaSecurityModule = await config.contracts.PoASecurityModule(poaSecurityModuleAddress);
1559
+ const balancerValidatorManagerAddress = await poaSecurityModule.read.balancerValidatorManager();
1560
+ const balancer = await config.contracts.BalancerValidatorManager(balancerValidatorManagerAddress);
1561
+ // Convert nodeID to Hex if necessary
1562
+ const nodeIdHex = (0, utils_1.parseNodeID)(nodeID, false);
1563
+ logger_1.logger.log(nodeIdHex);
1564
+ const validationId = await balancer.read.getNodeValidationID([nodeIdHex]);
1565
+ const txHash = await poaSecurityModule.safeWrite.initiateValidatorRemoval([validationId], {
1566
+ chain: null,
1567
+ account: config.client.account,
1568
+ });
1569
+ logger_1.logger.log(`End validation initialized for node ${nodeID}. Transaction hash: ${txHash}`);
1570
+ });
1571
+ poaCmd
1572
+ .command("complete-validator-removal")
1573
+ .description("Complete validator removal in the P-Chain and in the POA Security Module")
1574
+ .addArgument(argPoaSecurityModuleAddress)
1575
+ .addArgument((0, cliParser_1.ArgHex)("removeNodeTxHash", "Remove node transaction hash"))
1576
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
1577
+ .addOption(new extra_typings_1.Option("--skip-wait-api", "Don't wait for the validator to be visible through the P-Chain API"))
1578
+ .addOption(new extra_typings_1.Option("--node-id <nodeId>", "Node ID of the validator being removed").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserNodeID)))
1579
+ .addOption(new extra_typings_1.Option("--add-node-tx <addNodeTx>", "Add node transaction hash").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserHex)))
1580
+ .asyncAction({ signer: true }, async (config, poaSecurityModuleAddress, removeNodeTxHash, options) => {
1581
+ const opts = program.opts();
1582
+ if (!options.pchainTxPrivateKey)
1583
+ options.pchainTxPrivateKey = opts.privateKey;
1584
+ const poaSecurityModule = await config.contracts.PoASecurityModule(poaSecurityModuleAddress);
1585
+ const balancerSvc = await config.contracts.BalancerValidatorManager(await poaSecurityModule.read.balancerValidatorManager());
1586
+ // Check if P-Chain address have 0.000050000 AVAX for tx fees
1587
+ await (0, transferUtils_1.requirePChainBallance)(config.client, 50000n, opts.yes);
1588
+ const txHash = await (0, securityModule_1.completeValidatorRemoval)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : config.client, poaSecurityModule, balancerSvc, config, removeNodeTxHash, !options.skipWaitApi, options.nodeId.length > 0 ? options.nodeId : undefined, options.addNodeTx.length > 0 ? options.addNodeTx : undefined);
1589
+ logger_1.logger.log(`End validation initialized for node . Transaction hash: ${txHash}`);
1590
+ });
1591
+ poaCmd
1592
+ .command("init-weight-update")
1593
+ .description("Update validator weight")
1594
+ .addArgument(argPoaSecurityModuleAddress)
1595
+ .addArgument((0, cliParser_1.ArgNodeID)())
1596
+ .addArgument((0, cliParser_1.ArgBigInt)("newWeight", "New weight"))
1597
+ .asyncAction({ signer: true }, async (config, poaSecurityModuleAddress, nodeId, newWeight) => {
1598
+ const poaSecurityModule = await config.contracts.PoASecurityModule(poaSecurityModuleAddress);
1599
+ logger_1.logger.log("Calling function initializeValidatorStakeUpdate...");
1600
+ // Parse NodeID to bytes32 format
1601
+ const nodeIdHex32 = (0, utils_1.parseNodeID)(nodeId);
1602
+ const hash = await poaSecurityModule.safeWrite.initiateValidatorWeightUpdate([nodeIdHex32, newWeight]);
1603
+ logger_1.logger.log("initiateValidatorWeightUpdate executed successfully, tx hash:", hash);
1604
+ });
1605
+ poaCmd
1606
+ .command("complete-weight-update")
1607
+ .description("Complete validator weight update of all or specified node IDs")
1608
+ .addArgument(argMiddlewareAddress)
1609
+ .addArgument((0, cliParser_1.ArgHex)("validatorStakeUpdateTxHash", "Validator stake update transaction hash"))
1610
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
1611
+ .addOption(new extra_typings_1.Option("--node-id <nodeId>", "Node ID of the validator being removed").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserNodeID)))
1612
+ .asyncAction({ signer: true }, async (config, poaSecurityModuleAddress, weightUpdateTxHash, options) => {
1613
+ const opts = program.opts();
1614
+ if (!options.pchainTxPrivateKey)
1615
+ options.pchainTxPrivateKey = opts.privateKey;
1616
+ const poaSecurityModule = await config.contracts.PoASecurityModule(poaSecurityModuleAddress);
1617
+ // Check if P-Chain address have 0.000050000 AVAX for tx fees
1618
+ await (0, transferUtils_1.requirePChainBallance)(config.client, 50000n, opts.yes);
1619
+ const txHash = await (0, securityModule_1.completeWeightUpdate)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : config.client, poaSecurityModule, config, weightUpdateTxHash, options.nodeId.length > 0 ? options.nodeId : undefined);
1620
+ logger_1.logger.log(`Weight update completed for node . Transaction hash: ${txHash}`);
1621
+ });
1622
+ /**
1623
+ * --------------------------------------------------
1624
+ * KITE STAKING MANAGER
1625
+ * --------------------------------------------------
1626
+ */
1627
+ const kiteStakingManagerCmd = program
1628
+ .command("kite-staking-manager")
1629
+ .alias("ksm")
1630
+ .description("Commands to interact with KiteStakingManager contracts")
1631
+ .hook("preSubcommand", () => {
1632
+ const opts = program.opts();
1633
+ const newNet = opts.network === "custom" ? opts.network : chainList_1.chainList[opts.network].testnet ? "kiteaitestnet" : "kiteai";
1634
+ program.setOptionValue("network", newNet);
1635
+ });
1636
+ kiteStakingManagerCmd
1637
+ .command("info")
1638
+ .description("Get global configuration from KiteStakingManager")
1639
+ .addOption(optKiteStakingManagerAddress)
1640
+ .asyncAction(async (config, options) => {
1641
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1642
+ const info = await (0, kiteStaking_1.getKiteStakingManagerInfo)(kiteStakingManager);
1643
+ logger_1.logger.logJsonTree(info);
1644
+ });
1645
+ kiteStakingManagerCmd
1646
+ .command("validator-info")
1647
+ .description("Get comprehensive information for a validator on KiteStakingManager")
1648
+ .addOption(optKiteStakingManagerAddress)
1649
+ .addArgument((0, cliParser_1.ArgHex)("validationID", "Validation ID of the validator"))
1650
+ .asyncAction(async (config, validationID, options) => {
1651
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1652
+ const info = await (0, kiteStaking_1.getValidatorFullInfo)(kiteStakingManager, validationID);
1653
+ logger_1.logger.logJsonTree(info);
1654
+ });
1655
+ kiteStakingManagerCmd
1656
+ .command("delegator-info")
1657
+ .description("Get comprehensive information for a delegator on KiteStakingManager")
1658
+ .addOption(optKiteStakingManagerAddress)
1659
+ .addArgument((0, cliParser_1.ArgHex)("delegationID", "Delegation ID of the delegator"))
1660
+ .asyncAction(async (config, delegationID, options) => {
1661
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1662
+ const info = await (0, kiteStaking_1.getDelegatorFullInfo)(kiteStakingManager, delegationID);
1663
+ logger_1.logger.logJsonTree(info);
1664
+ });
1665
+ kiteStakingManagerCmd
1666
+ .command("update-staking-config")
1667
+ .description("Update staking configuration")
1668
+ .addOption(optKiteStakingManagerAddress)
1669
+ .argument("minimumStakeAmount", "Minimum stake amount")
1670
+ .argument("maximumStakeAmount", "Maximum stake amount")
1671
+ .argument("minimumStakeDuration", "Minimum stake duration in seconds")
1672
+ .addArgument((0, cliParser_1.ArgNumber)("minimumDelegationFeeBips", "Minimum delegation fee in basis points"))
1673
+ .addArgument((0, cliParser_1.ArgNumber)("maximumStakeMultiplier", "Maximum stake multiplier"))
1674
+ .asyncAction({ signer: true }, async (config, minimumStakeAmount, maximumStakeAmount, minimumStakeDuration, minimumDelegationFeeBips, maximumStakeMultiplier, options) => {
1675
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1676
+ // Get staking config to determine decimals - typically 18 for native tokens
1677
+ // For now, assume 18 decimals (1e18) for stake amounts
1678
+ const minimumStakeAmountWei = (0, viem_1.parseUnits)(minimumStakeAmount, 18);
1679
+ const maximumStakeAmountWei = (0, viem_1.parseUnits)(maximumStakeAmount, 18);
1680
+ const minimumStakeDurationBigInt = BigInt(minimumStakeDuration);
1681
+ await (0, kiteStaking_1.updateStakingConfig)(kiteStakingManager, minimumStakeAmountWei, maximumStakeAmountWei, minimumStakeDurationBigInt, minimumDelegationFeeBips, maximumStakeMultiplier);
1682
+ });
1683
+ kiteStakingManagerCmd
1684
+ .command("initiate-validator-registration")
1685
+ .description("Initiate validator registration on KiteStakingManager")
1686
+ .addOption(optKiteStakingManagerAddress)
1687
+ .addArgument((0, cliParser_1.ArgNodeID)())
1688
+ .addArgument((0, cliParser_1.ArgHex)("blsKey", "BLS public key"))
1689
+ .addArgument((0, cliParser_1.ArgNumber)("delegationFeeBips", "Delegation fee in basis points"))
1690
+ .argument("minStakeDuration", "Minimum stake duration in seconds")
1691
+ .addArgument((0, cliParser_1.ArgAddress)("rewardRecipient", "Reward recipient address"))
1692
+ .argument("stakeAmount", "Initial stake amount")
1693
+ .addOption(new extra_typings_1.Option("--pchain-remaining-balance-owner-threshold <threshold>", "P-Chain remaining balance owner threshold").default(1).argParser(cliParser_1.ParserNumber))
1694
+ .addOption(new extra_typings_1.Option("--pchain-disable-owner-threshold <threshold>", "P-Chain disable owner threshold").default(1).argParser(cliParser_1.ParserNumber))
1695
+ .addOption(new extra_typings_1.Option("--pchain-remaining-balance-owner-address <address>", "P-Chain remaining balance owner address").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserAddress)))
1696
+ .addOption(new extra_typings_1.Option("--pchain-disable-owner-address <address>", "P-Chain disable owner address").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserAddress)))
1697
+ .asyncAction({ signer: true }, async (config, nodeId, blsKey, delegationFeeBips, minStakeDuration, rewardRecipient, stakeAmount, options) => {
1698
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1699
+ const defaultOwnerAddress = (0, viem_1.fromBytes)(avalanchejs_1.utils.bech32ToBytes(config.client.addresses.P), 'hex');
1700
+ // Build remainingBalanceOwner and disableOwner PChainOwner structs
1701
+ const remainingBalanceOwnerAddress = options.pchainRemainingBalanceOwnerAddress.length > 0 ? options.pchainRemainingBalanceOwnerAddress : [defaultOwnerAddress];
1702
+ const disableOwnerAddress = options.pchainDisableOwnerAddress.length > 0 ? options.pchainDisableOwnerAddress : [defaultOwnerAddress];
1703
+ const remainingBalanceOwner = [
1704
+ Number(options.pchainRemainingBalanceOwnerThreshold),
1705
+ remainingBalanceOwnerAddress
1706
+ ];
1707
+ const disableOwner = [
1708
+ Number(options.pchainDisableOwnerThreshold),
1709
+ disableOwnerAddress
1710
+ ];
1711
+ // Get staking config to determine decimals for initial stake
1712
+ // For now, assume 18 decimals (1e18) for stake amounts
1713
+ const stakeAmountWei = (0, viem_1.parseUnits)(stakeAmount, 18);
1714
+ const minStakeDurationBigInt = BigInt(minStakeDuration);
1715
+ await (0, kiteStaking_1.initiateValidatorRegistration)(kiteStakingManager, nodeId, blsKey, remainingBalanceOwner, disableOwner, delegationFeeBips, minStakeDurationBigInt, rewardRecipient, stakeAmountWei);
1716
+ });
1717
+ kiteStakingManagerCmd
1718
+ .command("complete-validator-registration")
1719
+ .description("Complete validator registration on the P-Chain and on the KiteStakingManager after initiating registration")
1720
+ .addOption(optKiteStakingManagerAddress)
1721
+ .addArgument((0, cliParser_1.ArgHex)("initiateTxHash", "Initiate validator registration transaction hash"))
1722
+ .addArgument((0, cliParser_1.ArgBLSPOP)())
1723
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
1724
+ .addOption(new extra_typings_1.Option("--initial-balance <initialBalance>", "Node initial balance to pay for continuous fee").default('0.01'))
1725
+ .addOption(new extra_typings_1.Option("--skip-wait-api", "Don't wait for the validator to be visible through the P-Chain API"))
1726
+ .asyncAction(async (_, initiateTxHash, blsProofOfPossession, options) => {
1727
+ const opts = program.opts();
1728
+ // If pchainTxPrivateKey is not provided, use the private key
1729
+ if (!options.pchainTxPrivateKey) {
1730
+ options.pchainTxPrivateKey = opts.privateKey;
1731
+ }
1732
+ const initialBalance = (0, cliParser_1.ParseUnits)(options.initialBalance, 9, 'Invalid initial balance');
1733
+ const client = await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey, opts.safe);
1734
+ const config = (0, config_1.getConfig)(client, opts.wait, opts.skipAbiValidation);
1735
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1736
+ await (0, kiteStaking_1.completeValidatorRegistration)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : client, kiteStakingManager, config, blsProofOfPossession, initiateTxHash, initialBalance, !options.skipWaitApi);
1737
+ });
1738
+ kiteStakingManagerCmd
1739
+ .command("initiate-delegator-registration")
1740
+ .description("Initiate delegator registration on KiteStakingManager")
1741
+ .addOption(optKiteStakingManagerAddress)
1742
+ .addArgument((0, cliParser_1.ArgNodeID)())
1743
+ .addArgument((0, cliParser_1.ArgAddress)("rewardRecipient", "Reward recipient address"))
1744
+ .argument("stakeAmount", "Initial stake amount")
1745
+ .asyncAction({ signer: true }, async (config, nodeId, rewardRecipient, stakeAmount, options) => {
1746
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1747
+ // Get staking config to determine decimals for stake amount
1748
+ // For now, assume 18 decimals (1e18) for stake amounts
1749
+ const stakeAmountWei = (0, viem_1.parseUnits)(stakeAmount, 18);
1750
+ await (0, kiteStaking_1.initiateDelegatorRegistration)(kiteStakingManager, config, nodeId, rewardRecipient, stakeAmountWei);
1751
+ });
1752
+ kiteStakingManagerCmd
1753
+ .command("complete-delegator-registration")
1754
+ .description("Complete delegator registration on the P-Chain and on the KiteStakingManager after initiating registration")
1755
+ .addOption(optKiteStakingManagerAddress)
1756
+ .addArgument((0, cliParser_1.ArgHex)("initiateTxHash", "Initiate delegator registration transaction hash"))
1757
+ .argument("rpcUrl", "RPC URL for getting validator uptime")
1758
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
1759
+ .asyncAction({ signer: true }, async (config, initiateTxHash, rpcUrl, options) => {
1760
+ const opts = program.opts();
1761
+ if (!options.pchainTxPrivateKey)
1762
+ options.pchainTxPrivateKey = opts.privateKey;
1763
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1764
+ await (0, kiteStaking_1.completeDelegatorRegistration)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : config.client, kiteStakingManager, config, initiateTxHash, rpcUrl);
1765
+ });
1766
+ kiteStakingManagerCmd
1767
+ .command("initiate-delegator-removal")
1768
+ .description("Initiate delegator removal on KiteStakingManager")
1769
+ .addOption(optKiteStakingManagerAddress)
1770
+ .addArgument((0, cliParser_1.ArgHex)("delegationID", "Delegation ID"))
1771
+ .addOption(new extra_typings_1.Option("--include-uptime-proof", "Include uptime proof in the removal").default(false))
1772
+ .addOption(new extra_typings_1.Option("--rpc-url <rpcUrl>", "RPC URL for getting validator uptime (required if --include-uptime-proof is true)"))
1773
+ .asyncAction({ signer: true }, async (config, delegationID, options) => {
1774
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1775
+ await (0, kiteStaking_1.initiateDelegatorRemoval)(kiteStakingManager, config, delegationID, options.includeUptimeProof, options.rpcUrl);
1776
+ });
1777
+ kiteStakingManagerCmd
1778
+ .command("complete-delegator-removal")
1779
+ .description("Complete delegator removal on the P-Chain and on the KiteStakingManager after initiating removal")
1780
+ .addOption(optKiteStakingManagerAddress)
1781
+ .addArgument((0, cliParser_1.ArgHex)("initiateRemovalTxHash", "Initiate delegator removal transaction hash"))
1782
+ .argument("rpcUrl", "RPC URL for getting validator uptime")
1783
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
1784
+ .addOption(new extra_typings_1.Option("--skip-wait-api", "Don't wait for the validator to be visible through the P-Chain API"))
1785
+ .addOption(new extra_typings_1.Option("--delegation-id <delegationID>", "Delegation ID of the delegator being removed").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserHex)))
1786
+ .addOption(new extra_typings_1.Option("--initiate-tx <initiateTx>", "Initiate delegator registration transaction hash"))
1787
+ .asyncAction({ signer: true }, async (config, initiateRemovalTxHash, rpcUrl, options) => {
1788
+ const opts = program.opts();
1789
+ if (!options.pchainTxPrivateKey)
1790
+ options.pchainTxPrivateKey = opts.privateKey;
1791
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1792
+ // Check if P-Chain address have 0.000050000 AVAX for tx fees
1793
+ await (0, transferUtils_1.requirePChainBallance)(config.client, 50000n, opts.yes);
1794
+ await (0, kiteStaking_1.completeDelegatorRemoval)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : config.client, kiteStakingManager, config, initiateRemovalTxHash, rpcUrl, !options.skipWaitApi, options.delegationId.length > 0 ? options.delegationId : undefined, options.initiateTx ? options.initiateTx : undefined);
1795
+ });
1796
+ kiteStakingManagerCmd
1797
+ .command("initiate-validator-removal")
1798
+ .description("Initiate validator removal on KiteStakingManager")
1799
+ .addOption(optKiteStakingManagerAddress)
1800
+ .addArgument((0, cliParser_1.ArgNodeID)())
1801
+ .addOption(new extra_typings_1.Option("--include-uptime-proof", "Include uptime proof in the removal").default(false))
1802
+ .asyncAction({ signer: true }, async (config, nodeId, options) => {
1803
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1804
+ await (0, kiteStaking_1.initiateValidatorRemoval)(kiteStakingManager, config, nodeId, options.includeUptimeProof);
1805
+ });
1806
+ kiteStakingManagerCmd
1807
+ .command("complete-validator-removal")
1808
+ .description("Complete validator removal on the P-Chain and on the KiteStakingManager after initiating removal")
1809
+ .addOption(optKiteStakingManagerAddress)
1810
+ .addArgument((0, cliParser_1.ArgHex)("initiateRemovalTxHash", "Initiate validator removal transaction hash"))
1811
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
1812
+ .addOption(new extra_typings_1.Option("--skip-wait-api", "Don't wait for the validator to be visible through the P-Chain API"))
1813
+ .addOption(new extra_typings_1.Option("--node-id <nodeId>", "Node ID of the validator being removed").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserNodeID)))
1814
+ .addOption(new extra_typings_1.Option("--initiate-tx <initiateTx>", "Initiate validator registration transaction hash").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserHex)))
1815
+ .asyncAction({ signer: true }, async (config, initiateRemovalTxHash, options) => {
1816
+ const opts = program.opts();
1817
+ if (!options.pchainTxPrivateKey)
1818
+ options.pchainTxPrivateKey = opts.privateKey;
1819
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1820
+ // Check if P-Chain address have 0.000050000 AVAX for tx fees
1821
+ await (0, transferUtils_1.requirePChainBallance)(config.client, 50000n, opts.yes);
1822
+ await (0, kiteStaking_1.completeValidatorRemoval)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : config.client, kiteStakingManager, config, initiateRemovalTxHash, !options.skipWaitApi, options.nodeId.length > 0 ? options.nodeId : undefined, options.initiateTx.length > 0 ? options.initiateTx : undefined);
1823
+ });
1824
+ kiteStakingManagerCmd
1825
+ .command("submit-uptime-proof")
1826
+ .description("Submit uptime proof for a validator")
1827
+ .addOption(optKiteStakingManagerAddress)
1828
+ .addArgument((0, cliParser_1.ArgNodeID)("nodeId", "Node ID of the validator"))
1829
+ .argument("rpcUrl", "RPC URL for getting validator uptime")
1830
+ .asyncAction({ signer: true }, async (config, nodeId, rpcUrl, options) => {
1831
+ const kiteStakingManager = await config.contracts.KiteStakingManager(options.stakingManagerAddress);
1832
+ await (0, kiteStaking_1.submitUptimeProof)(config, kiteStakingManager, rpcUrl, nodeId);
1833
+ });
1834
+ /**
1835
+ * --------------------------------------------------
1836
+ * STAKING VAULT
1837
+ * --------------------------------------------------
1838
+ */
1839
+ const stakingVaultCmd = program
1840
+ .command("staking-vault")
1841
+ .alias("sv")
1842
+ .description("Commands to interact with StakingVault contracts")
1843
+ .hook("preSubcommand", () => {
1844
+ const opts = program.opts();
1845
+ const newNet = opts.network === "custom" ? opts.network : chainList_1.chainList[opts.network].testnet ? "kiteaitestnet" : "kiteai";
1846
+ program.setOptionValue("network", newNet);
1847
+ });
1848
+ stakingVaultCmd
1849
+ .command("deposit")
1850
+ .description("Deposit native tokens (AVAX) into the StakingVault")
1851
+ .addOption(optStakingVaultAddress)
1852
+ .argument("amount", "Amount to deposit in AVAX")
1853
+ .addArgument((0, cliParser_1.ArgBigInt)("minShares", "Minimum shares expected from the deposit (slippage protection)"))
1854
+ .asyncAction({ signer: true }, async (config, amount, minShares, options) => {
1855
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1856
+ await (0, stakingVault_1.depositStakingVault)(config.client, stakingVault, amount, minShares);
1857
+ });
1858
+ stakingVaultCmd
1859
+ .command("request-withdrawal")
1860
+ .description("Request withdrawal from the StakingVault")
1861
+ .addOption(optStakingVaultAddress)
1862
+ .argument("shares", "Amount of shares to withdraw")
1863
+ .asyncAction({ signer: true }, async (config, shares, options) => {
1864
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1865
+ await (0, stakingVault_1.requestWithdrawalStakingVault)(config.client, stakingVault, shares);
1866
+ });
1867
+ stakingVaultCmd
1868
+ .command("claim-withdrawal")
1869
+ .description("Claim a withdrawal from the StakingVault")
1870
+ .addOption(optStakingVaultAddress)
1871
+ .addArgument((0, cliParser_1.ArgBigInt)("requestId", "Withdrawal request ID to claim"))
1872
+ .asyncAction({ signer: true }, async (config, requestId, options) => {
1873
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1874
+ await (0, stakingVault_1.claimWithdrawalStakingVault)(config.client, stakingVault, requestId);
1875
+ });
1876
+ stakingVaultCmd
1877
+ .command("claim-withdrawal-for")
1878
+ .description("Claim a withdrawal for a request ID (permissionless)")
1879
+ .addOption(optStakingVaultAddress)
1880
+ .addArgument((0, cliParser_1.ArgBigInt)("requestId", "Withdrawal request ID to claim"))
1881
+ .asyncAction({ signer: true }, async (config, requestId, options) => {
1882
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1883
+ const hash = await stakingVault.safeWrite.claimWithdrawalFor([requestId]);
1884
+ logger_1.logger.log("claimWithdrawalFor tx hash:", hash);
1885
+ logger_1.logger.log("claimWithdrawalFor executed successfully");
1886
+ });
1887
+ stakingVaultCmd
1888
+ .command("claim-withdrawals-for")
1889
+ .description("Claim multiple withdrawals for request IDs (permissionless)")
1890
+ .addOption(optStakingVaultAddress)
1891
+ .argument("requestIds...", "Withdrawal request IDs to claim")
1892
+ .asyncAction({ signer: true }, async (config, requestIds, options) => {
1893
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1894
+ const ids = requestIds.map((id) => BigInt(id));
1895
+ const hash = await stakingVault.safeWrite.claimWithdrawalsFor([ids]);
1896
+ logger_1.logger.log("claimWithdrawalsFor tx hash:", hash);
1897
+ logger_1.logger.log("claimWithdrawalsFor executed successfully");
1898
+ });
1899
+ stakingVaultCmd
1900
+ .command("claim-escrowed-withdrawal")
1901
+ .description("Claim escrowed withdrawal to a recipient")
1902
+ .addOption(optStakingVaultAddress)
1903
+ .addArgument((0, cliParser_1.ArgAddress)("recipient", "Recipient address"))
1904
+ .asyncAction({ signer: true }, async (config, recipient, options) => {
1905
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1906
+ const hash = await stakingVault.safeWrite.claimEscrowedWithdrawal([recipient]);
1907
+ logger_1.logger.log("claimEscrowedWithdrawal tx hash:", hash);
1908
+ logger_1.logger.log("claimEscrowedWithdrawal executed successfully");
1909
+ });
1910
+ stakingVaultCmd
1911
+ .command("process-epoch")
1912
+ .description("Process the current epoch in the StakingVault")
1913
+ .addOption(optStakingVaultAddress)
1914
+ .asyncAction({ signer: true }, async (config, options) => {
1915
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1916
+ await (0, stakingVault_1.processEpochStakingVault)(config.client, stakingVault);
1917
+ });
1918
+ stakingVaultCmd
1919
+ .command("initiate-validator-registration")
1920
+ .description("Initiate validator registration in the StakingVault")
1921
+ .addOption(optStakingVaultAddress)
1922
+ .addArgument((0, cliParser_1.ArgNodeID)())
1923
+ .addArgument((0, cliParser_1.ArgHex)("blsKey", "BLS public key"))
1924
+ .argument("stakeAmount", "Stake amount in AVAX")
1925
+ .addOption(new extra_typings_1.Option("--pchain-remaining-balance-owner-threshold <threshold>", "P-Chain remaining balance owner threshold").default(1).argParser(cliParser_1.ParserNumber))
1926
+ .addOption(new extra_typings_1.Option("--pchain-disable-owner-threshold <threshold>", "P-Chain disable owner threshold").default(1).argParser(cliParser_1.ParserNumber))
1927
+ .addOption(new extra_typings_1.Option("--pchain-remaining-balance-owner-address <address>", "P-Chain remaining balance owner address").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserAddress)))
1928
+ .addOption(new extra_typings_1.Option("--pchain-disable-owner-address <address>", "P-Chain disable owner address").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserAddress)))
1929
+ .asyncAction({ signer: true }, async (config, nodeId, blsKey, stakeAmount, options) => {
1930
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1931
+ const defaultOwnerAddress = (0, viem_1.fromBytes)(avalanchejs_1.utils.bech32ToBytes(config.client.addresses.P), 'hex');
1932
+ // Build remainingBalanceOwner and disableOwner PChainOwner structs
1933
+ const remainingBalanceOwnerAddress = options.pchainRemainingBalanceOwnerAddress.length > 0 ? options.pchainRemainingBalanceOwnerAddress : [defaultOwnerAddress];
1934
+ const disableOwnerAddress = options.pchainDisableOwnerAddress.length > 0 ? options.pchainDisableOwnerAddress : [defaultOwnerAddress];
1935
+ const remainingBalanceOwner = [
1936
+ Number(options.pchainRemainingBalanceOwnerThreshold),
1937
+ remainingBalanceOwnerAddress
1938
+ ];
1939
+ const disableOwner = [
1940
+ Number(options.pchainDisableOwnerThreshold),
1941
+ disableOwnerAddress
1942
+ ];
1943
+ await (0, stakingVault_1.initiateValidatorRegistrationStakingVault)(config.client, stakingVault, nodeId, blsKey, remainingBalanceOwner, disableOwner, stakeAmount);
1944
+ });
1945
+ stakingVaultCmd
1946
+ .command("add-operator")
1947
+ .description("Add an operator to the StakingVault")
1948
+ .addOption(optStakingVaultAddress)
1949
+ .addArgument(argOperatorAddress)
1950
+ .argument("allocationBips", "Allocation in basis points (1 bips = 0.01%)")
1951
+ .addArgument((0, cliParser_1.ArgAddress)("feeRecipient", "Fee recipient address"))
1952
+ .asyncAction({ signer: true }, async (config, operator, allocationBips, feeRecipient, options) => {
1953
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1954
+ const allocationBipsBigInt = BigInt(allocationBips);
1955
+ await (0, stakingVault_1.addOperatorStakingVault)(config.client, stakingVault, operator, allocationBipsBigInt, feeRecipient);
1956
+ });
1957
+ stakingVaultCmd
1958
+ .command("remove-operator")
1959
+ .description("Remove an operator from the StakingVault")
1960
+ .addOption(optStakingVaultAddress)
1961
+ .addArgument(argOperatorAddress)
1962
+ .asyncAction({ signer: true }, async (config, operator, options) => {
1963
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1964
+ const hash = await stakingVault.safeWrite.removeOperator([operator]);
1965
+ logger_1.logger.log("removeOperator tx hash:", hash);
1966
+ logger_1.logger.log("removeOperator executed successfully");
1967
+ });
1968
+ stakingVaultCmd
1969
+ .command("complete-validator-registration")
1970
+ .description("Complete validator registration on the P-Chain and on the StakingVault after initiating registration")
1971
+ .addOption(optStakingVaultAddress)
1972
+ .addArgument((0, cliParser_1.ArgHex)("initiateTxHash", "Initiate validator registration transaction hash"))
1973
+ .addArgument((0, cliParser_1.ArgBLSPOP)())
1974
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
1975
+ .addOption(new extra_typings_1.Option("--initial-balance <initialBalance>", "Node initial balance to pay for continuous fee").default('0.01'))
1976
+ .addOption(new extra_typings_1.Option("--skip-wait-api", "Don't wait for the validator to be visible through the P-Chain API"))
1977
+ .asyncAction(async (_, initiateTxHash, blsProofOfPossession, options) => {
1978
+ const opts = program.opts();
1979
+ // If pchainTxPrivateKey is not provided, use the private key
1980
+ if (!options.pchainTxPrivateKey) {
1981
+ options.pchainTxPrivateKey = opts.privateKey;
1982
+ }
1983
+ const initialBalance = (0, cliParser_1.ParseUnits)(options.initialBalance, 9, 'Invalid initial balance');
1984
+ const client = await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey, opts.safe);
1985
+ const config = (0, config_1.getConfig)(client, opts.wait, opts.skipAbiValidation);
1986
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1987
+ const { validatorManagerAddress } = await (0, stakingVault_1.getValidatorManagerAddress)(config, stakingVault);
1988
+ const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress);
1989
+ await (0, stakingVault_1.completeValidatorRegistrationStakingVault)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : client, config, stakingVault, validatorManager, blsProofOfPossession, initiateTxHash, initialBalance, !options.skipWaitApi);
1990
+ });
1991
+ stakingVaultCmd
1992
+ .command("initiate-validator-removal")
1993
+ .description("Initiate validator removal in the StakingVault")
1994
+ .addOption(optStakingVaultAddress)
1995
+ .addArgument((0, cliParser_1.ArgNodeID)())
1996
+ .asyncAction({ signer: true }, async (config, nodeId, options) => {
1997
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
1998
+ const { validatorManagerAddress } = await (0, stakingVault_1.getValidatorManagerAddress)(config, stakingVault);
1999
+ const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress);
2000
+ await (0, stakingVault_1.initiateValidatorRemovalStakingVault)(config.client, stakingVault, validatorManager, nodeId);
2001
+ });
2002
+ stakingVaultCmd
2003
+ .command("complete-validator-removal")
2004
+ .description("Complete validator removal on the P-Chain and on the StakingVault after initiating removal")
2005
+ .addOption(optStakingVaultAddress)
2006
+ .addArgument((0, cliParser_1.ArgHex)("initiateRemovalTxHash", "Initiate validator removal transaction hash"))
2007
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
2008
+ .addOption(new extra_typings_1.Option("--skip-wait-api", "Don't wait for the validator to be removed from the P-Chain API"))
2009
+ .addOption(new extra_typings_1.Option("--node-id <nodeId>", "Node ID of the validator being removed").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserNodeID)))
2010
+ .addOption(new extra_typings_1.Option("--initiate-tx <initiateTx>", "Initiate validator registration transaction hash").argParser((value) => value))
2011
+ .asyncAction({ signer: true }, async (config, initiateRemovalTxHash, options) => {
2012
+ const opts = program.opts();
2013
+ if (!options.pchainTxPrivateKey)
2014
+ options.pchainTxPrivateKey = opts.privateKey;
2015
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2016
+ const { validatorManagerAddress } = await (0, stakingVault_1.getValidatorManagerAddress)(config, stakingVault);
2017
+ const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress);
2018
+ // Check if P-Chain address have 0.000050000 AVAX for tx fees
2019
+ await (0, transferUtils_1.requirePChainBallance)(config.client, 50000n, opts.yes);
2020
+ await (0, stakingVault_1.completeValidatorRemovalStakingVault)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : config.client, config, stakingVault, validatorManager, initiateRemovalTxHash, !options.skipWaitApi, options.nodeId.length > 0 ? options.nodeId : undefined, options.initiateTx);
2021
+ });
2022
+ stakingVaultCmd
2023
+ .command("force-remove-validator")
2024
+ .description("Force remove a validator from the StakingVault (admin/emergency operation)")
2025
+ .addOption(optStakingVaultAddress)
2026
+ .addArgument((0, cliParser_1.ArgNodeID)())
2027
+ .asyncAction({ signer: true }, async (config, nodeId, options) => {
2028
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2029
+ const { validatorManagerAddress } = await (0, stakingVault_1.getValidatorManagerAddress)(config, stakingVault);
2030
+ const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress);
2031
+ await (0, stakingVault_1.forceRemoveValidatorStakingVault)(config.client, stakingVault, validatorManager, nodeId);
2032
+ });
2033
+ stakingVaultCmd
2034
+ .command("initiate-delegator-registration")
2035
+ .description("Initiate delegator registration in the StakingVault")
2036
+ .addOption(optStakingVaultAddress)
2037
+ .addArgument((0, cliParser_1.ArgNodeID)())
2038
+ .argument("amount", "Stake amount in AVAX")
2039
+ .asyncAction({ signer: true }, async (config, nodeId, amount, options) => {
2040
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2041
+ const { validatorManagerAddress } = await (0, stakingVault_1.getValidatorManagerAddress)(config, stakingVault);
2042
+ const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress);
2043
+ await (0, stakingVault_1.initiateDelegatorRegistrationStakingVault)(config.client, stakingVault, validatorManager, nodeId, amount);
2044
+ });
2045
+ stakingVaultCmd
2046
+ .command("complete-delegator-registration")
2047
+ .description("Complete delegator registration on the P-Chain and on the StakingVault after initiating registration")
2048
+ .addOption(optStakingVaultAddress)
2049
+ .addArgument((0, cliParser_1.ArgHex)("initiateTxHash", "Initiate delegator registration transaction hash"))
2050
+ .argument("rpcUrl", "RPC URL for getting validator uptime (e.g. http(s)://domainOrIp:portIfNeeded)")
2051
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
2052
+ .asyncAction({ signer: true }, async (config, initiateTxHash, rpcUrl, options) => {
2053
+ const opts = program.opts();
2054
+ if (!options.pchainTxPrivateKey)
2055
+ options.pchainTxPrivateKey = opts.privateKey;
2056
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2057
+ const { validatorManagerAddress, stakingManager, stakingManagerStorageLocation } = await (0, stakingVault_1.getValidatorManagerAddress)(config, stakingVault);
2058
+ const uptimeBlockchainID = await config.client.getStorageAt({ address: stakingManager.address, slot: `0x${(BigInt(stakingManagerStorageLocation) + 6n).toString(16).padStart(64, '0')}` });
2059
+ if (!uptimeBlockchainID || uptimeBlockchainID === "0x0") {
2060
+ throw new Error("Could not get uptime blockchain ID");
2061
+ }
2062
+ const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress);
2063
+ await (0, stakingVault_1.completeDelegatorRegistrationStakingVault)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : config.client, config, stakingVault, validatorManager, initiateTxHash, rpcUrl, uptimeBlockchainID);
2064
+ });
2065
+ stakingVaultCmd
2066
+ .command("initiate-delegator-removal")
2067
+ .description("Initiate delegator removal in the StakingVault")
2068
+ .addOption(optStakingVaultAddress)
2069
+ .addArgument((0, cliParser_1.ArgHex)("delegationID", "Delegation ID"))
2070
+ .asyncAction({ signer: true }, async (config, delegationID, options) => {
2071
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2072
+ await (0, stakingVault_1.initiateDelegatorRemovalStakingVault)(config.client, stakingVault, delegationID);
2073
+ });
2074
+ stakingVaultCmd
2075
+ .command("force-remove-delegator")
2076
+ .description("Force remove a delegator from the StakingVault (admin/emergency operation)")
2077
+ .addOption(optStakingVaultAddress)
2078
+ .addArgument((0, cliParser_1.ArgHex)("delegationID", "Delegation ID"))
2079
+ .asyncAction({ signer: true }, async (config, delegationID, options) => {
2080
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2081
+ await (0, stakingVault_1.forceRemoveDelegatorStakingVault)(config.client, stakingVault, delegationID);
2082
+ });
2083
+ stakingVaultCmd
2084
+ .command("complete-delegator-removal")
2085
+ .description("Complete delegator removal on the P-Chain and on the StakingVault after initiating removal")
2086
+ .addOption(optStakingVaultAddress)
2087
+ .addArgument((0, cliParser_1.ArgHex)("initiateRemovalTxHash", "Initiate delegator removal transaction hash"))
2088
+ .addOption(new extra_typings_1.Option("--pchain-tx-private-key <pchainTxPrivateKey>", "P-Chain transaction private key/secret name or 'ledger'. Defaults to the private key.").argParser(cliParser_1.ParserPrivateKey))
2089
+ .addOption(new extra_typings_1.Option("--skip-wait-api", "Don't wait for the validator to be removed from the P-Chain API"))
2090
+ .addOption(new extra_typings_1.Option("--delegation-id <delegationID>", "Delegation ID of the delegator being removed").default([]).argParser((0, cliParser_1.collectMultiple)(cliParser_1.ParserHex)))
2091
+ .addOption(new extra_typings_1.Option("--initiate-tx <initiateTx>", "Initiate delegator registration transaction hash").argParser((value) => value))
2092
+ .asyncAction({ signer: true }, async (config, initiateRemovalTxHash, options) => {
2093
+ const opts = program.opts();
2094
+ if (!options.pchainTxPrivateKey)
2095
+ options.pchainTxPrivateKey = opts.privateKey;
2096
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2097
+ const { validatorManagerAddress } = await (0, stakingVault_1.getValidatorManagerAddress)(config, stakingVault);
2098
+ const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress);
2099
+ // Check if P-Chain address have 0.000050000 AVAX for tx fees
2100
+ await (0, transferUtils_1.requirePChainBallance)(config.client, 50000n, opts.yes);
2101
+ await (0, stakingVault_1.completeDelegatorRemovalStakingVault)(options.pchainTxPrivateKey ? await (0, client_1.generateClient)(opts.network, options.pchainTxPrivateKey) : config.client, config, stakingVault, validatorManager, initiateRemovalTxHash, options.delegationId.length > 0 ? options.delegationId : undefined, options.initiateTx);
2102
+ });
2103
+ stakingVaultCmd
2104
+ .command("update-operator-allocations")
2105
+ .description("Update operator allocations in the StakingVault")
2106
+ .addOption(optStakingVaultAddress)
2107
+ .addArgument(argOperatorAddress)
2108
+ .argument("allocationBips", "Allocation in basis points (1 bips = 0.01%)")
2109
+ .asyncAction({ signer: true }, async (config, operator, allocationBips, options) => {
2110
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2111
+ const allocationBipsBigInt = BigInt(allocationBips);
2112
+ await stakingVault.safeWrite.updateOperatorAllocations([[operator], [allocationBipsBigInt]]);
2113
+ });
2114
+ stakingVaultCmd
2115
+ .command("claim-operator-fees")
2116
+ .description("Claim operator fees for the caller")
2117
+ .addOption(optStakingVaultAddress)
2118
+ .asyncAction({ signer: true }, async (config, options) => {
2119
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2120
+ const hash = await stakingVault.safeWrite.claimOperatorFees([]);
2121
+ logger_1.logger.log("claimOperatorFees executed successfully, tx hash:", hash);
2122
+ });
2123
+ stakingVaultCmd
2124
+ .command("force-claim-operator-fees")
2125
+ .description("Force claim operator fees for an operator (admin)")
2126
+ .addOption(optStakingVaultAddress)
2127
+ .addArgument(argOperatorAddress)
2128
+ .asyncAction({ signer: true }, async (config, operator, options) => {
2129
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2130
+ const hash = await stakingVault.safeWrite.forceClaimOperatorFees([operator]);
2131
+ logger_1.logger.log("forceClaimOperatorFees executed successfully, tx hash:", hash);
2132
+ });
2133
+ stakingVaultCmd
2134
+ .command("claim-pending-protocol-fees")
2135
+ .description("Claim pending protocol fees")
2136
+ .addOption(optStakingVaultAddress)
2137
+ .asyncAction({ signer: true }, async (config, options) => {
2138
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2139
+ const hash = await stakingVault.safeWrite.claimPendingProtocolFees([]);
2140
+ logger_1.logger.log("claimPendingProtocolFees executed successfully, tx hash:", hash);
2141
+ });
2142
+ stakingVaultCmd
2143
+ .command("harvest")
2144
+ .description("Harvest rewards")
2145
+ .addOption(optStakingVaultAddress)
2146
+ .asyncAction({ signer: true }, async (config, options) => {
2147
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2148
+ const hash = await stakingVault.safeWrite.harvest([]);
2149
+ logger_1.logger.log("harvest executed successfully, tx hash:", hash);
2150
+ });
2151
+ stakingVaultCmd
2152
+ .command("harvest-validators")
2153
+ .description("Harvest validator rewards in batches")
2154
+ .addOption(optStakingVaultAddress)
2155
+ .addArgument((0, cliParser_1.ArgBigInt)("operatorIndex", "Operator index"))
2156
+ .addArgument((0, cliParser_1.ArgBigInt)("start", "Validator list start index"))
2157
+ .addArgument((0, cliParser_1.ArgBigInt)("batchSize", "Validator batch size"))
2158
+ .asyncAction({ signer: true }, async (config, operatorIndex, start, batchSize, options) => {
2159
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2160
+ const hash = await stakingVault.safeWrite.harvestValidators([operatorIndex, start, batchSize]);
2161
+ logger_1.logger.log("harvestValidators executed successfully, tx hash:", hash);
2162
+ });
2163
+ stakingVaultCmd
2164
+ .command("harvest-delegators")
2165
+ .description("Harvest delegator rewards in batches")
2166
+ .addOption(optStakingVaultAddress)
2167
+ .addArgument((0, cliParser_1.ArgBigInt)("operatorIndex", "Operator index"))
2168
+ .addArgument((0, cliParser_1.ArgBigInt)("start", "Delegator list start index"))
2169
+ .addArgument((0, cliParser_1.ArgBigInt)("batchSize", "Delegator batch size"))
2170
+ .asyncAction({ signer: true }, async (config, operatorIndex, start, batchSize, options) => {
2171
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2172
+ const hash = await stakingVault.safeWrite.harvestDelegators([operatorIndex, start, batchSize]);
2173
+ logger_1.logger.log("harvestDelegators executed successfully, tx hash:", hash);
2174
+ });
2175
+ stakingVaultCmd
2176
+ .command("prepare-withdrawals")
2177
+ .description("Prepare withdrawals by initiating stake removals")
2178
+ .addOption(optStakingVaultAddress)
2179
+ .asyncAction({ signer: true }, async (config, options) => {
2180
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2181
+ const hash = await stakingVault.safeWrite.prepareWithdrawals([]);
2182
+ logger_1.logger.log("prepareWithdrawals executed successfully, tx hash:", hash);
2183
+ });
2184
+ stakingVaultCmd
2185
+ .command("pause")
2186
+ .description("Pause the StakingVault")
2187
+ .addOption(optStakingVaultAddress)
2188
+ .asyncAction({ signer: true }, async (config, options) => {
2189
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2190
+ const hash = await stakingVault.safeWrite.pause([]);
2191
+ logger_1.logger.log("pause executed successfully, tx hash:", hash);
2192
+ });
2193
+ stakingVaultCmd
2194
+ .command("unpause")
2195
+ .description("Unpause the StakingVault")
2196
+ .addOption(optStakingVaultAddress)
2197
+ .asyncAction({ signer: true }, async (config, options) => {
2198
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2199
+ const hash = await stakingVault.safeWrite.unpause([]);
2200
+ logger_1.logger.log("unpause executed successfully, tx hash:", hash);
2201
+ });
2202
+ /**
2203
+ * Setters
2204
+ */
2205
+ stakingVaultCmd
2206
+ .command("set-liquidity-buffer-bips")
2207
+ .description("Set the liquidity buffer in basis points")
2208
+ .addOption(optStakingVaultAddress)
2209
+ .addArgument((0, cliParser_1.ArgBigInt)("liquidityBufferBips", "Liquidity buffer in basis points"))
2210
+ .asyncAction({ signer: true }, async (config, liquidityBufferBips, options) => {
2211
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2212
+ const hash = await stakingVault.safeWrite.setLiquidityBufferBips([liquidityBufferBips]);
2213
+ logger_1.logger.log("setLiquidityBufferBips executed successfully, tx hash:", hash);
2214
+ });
2215
+ stakingVaultCmd
2216
+ .command("set-withdrawal-request-fee")
2217
+ .description("Set the withdrawal request fee")
2218
+ .addOption(optStakingVaultAddress)
2219
+ .addArgument((0, cliParser_1.ArgBigInt)("fee", "Withdrawal request fee"))
2220
+ .asyncAction({ signer: true }, async (config, fee, options) => {
2221
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2222
+ const hash = await stakingVault.safeWrite.setWithdrawalRequestFee([fee]);
2223
+ logger_1.logger.log("setWithdrawalRequestFee executed successfully, tx hash:", hash);
2224
+ });
2225
+ stakingVaultCmd
2226
+ .command("set-max-operators")
2227
+ .description("Set the maximum number of operators")
2228
+ .addOption(optStakingVaultAddress)
2229
+ .addArgument((0, cliParser_1.ArgBigInt)("maxOperators", "Maximum number of operators"))
2230
+ .asyncAction({ signer: true }, async (config, maxOperators, options) => {
2231
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2232
+ const hash = await stakingVault.safeWrite.setMaxOperators([maxOperators]);
2233
+ logger_1.logger.log("setMaxOperators executed successfully, tx hash:", hash);
2234
+ });
2235
+ stakingVaultCmd
2236
+ .command("set-max-validators-per-operator")
2237
+ .description("Set the maximum number of validators per operator")
2238
+ .addOption(optStakingVaultAddress)
2239
+ .addArgument((0, cliParser_1.ArgBigInt)("maxValidatorsPerOperator", "Maximum number of validators per operator"))
2240
+ .asyncAction({ signer: true }, async (config, maxValidatorsPerOperator, options) => {
2241
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2242
+ const hash = await stakingVault.safeWrite.setMaxValidatorsPerOperator([maxValidatorsPerOperator]);
2243
+ logger_1.logger.log("setMaxValidatorsPerOperator executed successfully, tx hash:", hash);
2244
+ });
2245
+ stakingVaultCmd
2246
+ .command("set-maximum-delegator-stake")
2247
+ .description("Set the maximum stake amount for a delegator")
2248
+ .addOption(optStakingVaultAddress)
2249
+ .addArgument((0, cliParser_1.ArgBigInt)("maximumDelegatorStake", "Maximum stake amount for a delegator"))
2250
+ .asyncAction({ signer: true }, async (config, maximumDelegatorStake, options) => {
2251
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2252
+ const hash = await stakingVault.safeWrite.setMaximumDelegatorStake([maximumDelegatorStake]);
2253
+ logger_1.logger.log("setMaximumDelegatorStake executed successfully, tx hash:", hash);
2254
+ });
2255
+ stakingVaultCmd
2256
+ .command("set-maximum-validator-stake")
2257
+ .description("Set the maximum stake amount for a validator")
2258
+ .addOption(optStakingVaultAddress)
2259
+ .addArgument((0, cliParser_1.ArgBigInt)("maximumValidatorStake", "Maximum stake amount for a validator"))
2260
+ .asyncAction({ signer: true }, async (config, maximumValidatorStake, options) => {
2261
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2262
+ const hash = await stakingVault.safeWrite.setMaximumValidatorStake([maximumValidatorStake]);
2263
+ logger_1.logger.log("setMaximumValidatorStake executed successfully, tx hash:", hash);
2264
+ });
2265
+ stakingVaultCmd
2266
+ .command("set-operations-impl")
2267
+ .description("Set the operations implementation")
2268
+ .addOption(optStakingVaultAddress)
2269
+ .addArgument((0, cliParser_1.ArgAddress)("operationsImpl", "Operations implementation"))
2270
+ .asyncAction({ signer: true }, async (config, operationsImpl, options) => {
2271
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2272
+ const hash = await stakingVault.safeWrite.setOperationsImpl([operationsImpl]);
2273
+ logger_1.logger.log("setOperationsImpl executed successfully, tx hash:", hash);
2274
+ });
2275
+ stakingVaultCmd
2276
+ .command("set-operator-fee-bips")
2277
+ .description("Set the operator fee in basis points")
2278
+ .addOption(optStakingVaultAddress)
2279
+ .addArgument((0, cliParser_1.ArgBigInt)("operatorFeeBips", "Operator fee in basis points"))
2280
+ .asyncAction({ signer: true }, async (config, operatorFeeBips, options) => {
2281
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2282
+ const hash = await stakingVault.safeWrite.setOperatorFeeBips([operatorFeeBips]);
2283
+ logger_1.logger.log("setOperatorFeeBips executed successfully, tx hash:", hash);
2284
+ });
2285
+ stakingVaultCmd
2286
+ .command("set-operator-fee-recipient")
2287
+ .description("Set the operator fee recipient")
2288
+ .addOption(optStakingVaultAddress)
2289
+ .addArgument((0, cliParser_1.ArgAddress)("operatorFeeRecipient", "Operator fee recipient"))
2290
+ .asyncAction({ signer: true }, async (config, operatorFeeRecipient, options) => {
2291
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2292
+ const hash = await stakingVault.safeWrite.setOperatorFeeRecipient([operatorFeeRecipient]);
2293
+ logger_1.logger.log("setOperatorFeeRecipient executed successfully, tx hash:", hash);
2294
+ });
2295
+ stakingVaultCmd
2296
+ .command("set-protocol-fee-bips")
2297
+ .description("Set the protocol fee in basis points")
2298
+ .addOption(optStakingVaultAddress)
2299
+ .addArgument((0, cliParser_1.ArgBigInt)("protocolFeeBips", "Protocol fee in basis points"))
2300
+ .asyncAction({ signer: true }, async (config, protocolFeeBips, options) => {
2301
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2302
+ const hash = await stakingVault.safeWrite.setProtocolFeeBips([protocolFeeBips]);
2303
+ logger_1.logger.log("setProtocolFeeBips executed successfully, tx hash:", hash);
2304
+ });
2305
+ stakingVaultCmd
2306
+ .command("set-protocol-fee-recipient")
2307
+ .description("Set the protocol fee recipient")
2308
+ .addOption(optStakingVaultAddress)
2309
+ .addArgument((0, cliParser_1.ArgAddress)("protocolFeeRecipient", "Protocol fee recipient"))
2310
+ .asyncAction({ signer: true }, async (config, protocolFeeRecipient, options) => {
2311
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2312
+ const hash = await stakingVault.safeWrite.setProtocolFeeRecipient([protocolFeeRecipient]);
2313
+ logger_1.logger.log("setProtocolFeeRecipient executed successfully, tx hash:", hash);
2314
+ });
2315
+ stakingVaultCmd
2316
+ .command("get-withdrawal-request-fee")
2317
+ .description("Get the withdrawal request fee")
2318
+ .addOption(optStakingVaultAddress)
2319
+ .asyncAction(async (config, options) => {
2320
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2321
+ const fee = await stakingVault.read.getWithdrawalRequestFee();
2322
+ logger_1.logger.log("Withdrawal request fee:", fee);
2323
+ });
2324
+ stakingVaultCmd
2325
+ .command("info")
2326
+ .description("Get general overview of the StakingVault")
2327
+ .addOption(optStakingVaultAddress)
2328
+ .asyncAction({ signer: true }, async (config, options) => {
2329
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2330
+ await (0, stakingVault_1.getGeneralInfo)(stakingVault, config.client);
2331
+ });
2332
+ stakingVaultCmd
2333
+ .command("fees-info")
2334
+ .description("Get fees configuration of the StakingVault")
2335
+ .addOption(optStakingVaultAddress)
2336
+ .asyncAction(async (config, options) => {
2337
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2338
+ await (0, stakingVault_1.getFeesInfo)(stakingVault);
2339
+ });
2340
+ stakingVaultCmd
2341
+ .command("operators-info")
2342
+ .description("Get operators details of the StakingVault")
2343
+ .addOption(optStakingVaultAddress)
2344
+ .asyncAction(async (config, options) => {
2345
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2346
+ await (0, stakingVault_1.getOperatorsInfo)(stakingVault);
2347
+ });
2348
+ stakingVaultCmd
2349
+ .command("validators-info")
2350
+ .description("Get validators details per operator of the StakingVault")
2351
+ .addOption(optStakingVaultAddress)
2352
+ .asyncAction(async (config, options) => {
2353
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2354
+ await (0, stakingVault_1.getValidatorsInfo)(stakingVault);
2355
+ });
2356
+ stakingVaultCmd
2357
+ .command("delegators-info")
2358
+ .description("Get delegations details per operator of the StakingVault")
2359
+ .addOption(optStakingVaultAddress)
2360
+ .asyncAction(async (config, options) => {
2361
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2362
+ await (0, stakingVault_1.getDelegatorsInfo)(stakingVault);
2363
+ });
2364
+ stakingVaultCmd
2365
+ .command("withdrawals-info")
2366
+ .description("Get withdrawal queue info of the StakingVault")
2367
+ .addOption(optStakingVaultAddress)
2368
+ .asyncAction(async (config, options) => {
2369
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2370
+ await (0, stakingVault_1.getWithdrawalsInfo)(stakingVault);
2371
+ });
2372
+ stakingVaultCmd
2373
+ .command("epoch-info")
2374
+ .description("Get epoch info of the StakingVault")
2375
+ .addOption(optStakingVaultAddress)
2376
+ .asyncAction(async (config, options) => {
2377
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2378
+ await (0, stakingVault_1.getEpochInfo)(stakingVault);
2379
+ });
2380
+ stakingVaultCmd
2381
+ .command("full-info")
2382
+ .description("Get all information about the StakingVault")
2383
+ .addOption(optStakingVaultAddress)
2384
+ .asyncAction(async (config, options) => {
2385
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2386
+ await (0, stakingVault_1.getGeneralInfo)(stakingVault, config.client);
2387
+ await (0, stakingVault_1.getFeesInfo)(stakingVault);
2388
+ await (0, stakingVault_1.getOperatorsInfo)(stakingVault);
2389
+ await (0, stakingVault_1.getValidatorsInfo)(stakingVault);
2390
+ await (0, stakingVault_1.getDelegatorsInfo)(stakingVault);
2391
+ await (0, stakingVault_1.getWithdrawalsInfo)(stakingVault);
2392
+ await (0, stakingVault_1.getEpochInfo)(stakingVault);
2393
+ });
2394
+ stakingVaultCmd
2395
+ .command("get-current-epoch")
2396
+ .description("Get current epoch number of the StakingVault")
2397
+ .addOption(optStakingVaultAddress)
2398
+ .asyncAction(async (config, options) => {
2399
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2400
+ const currentEpoch = await stakingVault.read.getCurrentEpoch();
2401
+ logger_1.logger.log(`Current epoch: ${currentEpoch}`);
2402
+ });
2403
+ stakingVaultCmd
2404
+ .command("get-epoch-duration")
2405
+ .description("Get epoch duration in seconds of the StakingVault")
2406
+ .addOption(optStakingVaultAddress)
2407
+ .asyncAction(async (config, options) => {
2408
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2409
+ const epochDuration = await stakingVault.read.getEpochDuration();
2410
+ logger_1.logger.log(`Epoch duration (seconds): ${epochDuration}`);
2411
+ });
2412
+ stakingVaultCmd
2413
+ .command("get-next-epoch-start-time")
2414
+ .description("Get next epoch start time (timestamp) of the StakingVault")
2415
+ .addOption(optStakingVaultAddress)
2416
+ .asyncAction(async (config, options) => {
2417
+ const stakingVault = await config.contracts.StakingVault(options.stakingVaultAddress);
2418
+ const startTime = await stakingVault.read.getStartTime();
2419
+ const [epochDuration, currentEpoch] = await stakingVault.multicall(["getEpochDuration", "getCurrentEpoch"]);
2420
+ const nextEpochStartTime = startTime + (epochDuration * (currentEpoch + 1n));
2421
+ const nextEpochStartDate = new Date(Number(nextEpochStartTime) * 1000);
2422
+ logger_1.logger.log(`Next epoch start time (timestamp): ${nextEpochStartTime} => ${nextEpochStartDate.toLocaleString()}`);
2423
+ });
2424
+ /**
2425
+ * --------------------------------------------------
2426
+ * OP-STAKES: enumerates the vaults and attempts to read stake for <operator>
2427
+ * --------------------------------------------------
2428
+ */
2429
+ vaultManagerCmd
2430
+ .command("opstakes")
2431
+ .description("Show operator stakes across L1s, enumerating each L1 the operator is opted into.")
2432
+ .addArgument(argMiddlewareVaultManagerAddress)
2433
+ .addArgument(argOperatorAddress)
2434
+ .description("Show operator stakes across L1s, enumerating each L1 the operator is opted into.")
2435
+ .asyncAction(async (config, middlewareVaultManager, operatorAddress) => {
2436
+ const operator = operatorAddress;
2437
+ logger_1.logger.log(`Operator: ${operator}`);
2438
+ // 1) Read total vaults from VaultManager
2439
+ const vaultManager = await config.contracts.VaultManager(middlewareVaultManager);
2440
+ const vaultCount = await vaultManager.read.getVaultCount();
2441
+ logger_1.logger.log(`Found ${vaultCount} vault(s).`);
2442
+ // This map accumulates the total stake for each collateral
2443
+ const totalStakesByCollateral = {};
2444
+ // 2) Let's get all L1 addresses from the L1Registry (similar to your Python code)
2445
+ const l1Registry = await config.contracts.L1Registry();
2446
+ const totalL1s = await l1Registry.read.totalL1s();
2447
+ // We'll store them in an array
2448
+ const l1Array = [];
2449
+ for (let i = 0n; i < totalL1s; i++) {
2450
+ // e.g. getL1At(i) might return [address, metadataUrl], adjust as needed
2451
+ const [l1Address, _] = await l1Registry.read.getL1At([i]);
2452
+ l1Array.push(l1Address);
2453
+ }
2454
+ // 3) For each vault in [0..vaultCount-1], read collateralClass, delegator, collateral
2455
+ for (let i = 0n; i < vaultCount; i++) {
2456
+ const [vaultAddress] = await vaultManager.read.getVaultAtWithTimes([i]);
2457
+ logger_1.logger.log(`\nVault #${i}: ${vaultAddress}`);
2458
+ // read the collateralClass
2459
+ const collateralClass = await vaultManager.read.getVaultCollateralClass([vaultAddress]);
2460
+ // read delegator
2461
+ const vaultTokenized = await config.contracts.VaultTokenized(vaultAddress);
2462
+ const delegator = await vaultTokenized.read.delegator();
2463
+ if (delegator === '0x0000000000000000000000000000000000000000') {
2464
+ logger_1.logger.log(" (No delegator set, skipping)");
2465
+ continue;
2466
+ }
2467
+ const l1RestakeDelegator = await config.contracts.L1RestakeDelegator(delegator);
2468
+ // read collateral
2469
+ const collateral = await vaultTokenized.read.collateral();
2470
+ // 4) For each L1 in l1Array, check if operator is opted in
2471
+ for (const l1Address of l1Array) {
2472
+ const operatorL1OptInService = await config.contracts.OperatorL1OptInService();
2473
+ const isOptedIn = await operatorL1OptInService.read.isOptedIn([operator, l1Address]);
2474
+ if (isOptedIn) {
2475
+ // read stake
2476
+ const stakeValue = await l1RestakeDelegator.read.stake([l1Address, collateralClass, operator]);
2477
+ if (stakeValue > 0n) {
2478
+ logger_1.logger.log(` L1: ${l1Address} => stake = ${stakeValue.toString()} (vault=${vaultAddress})`);
2479
+ // sum into totalStakesByCollateral
2480
+ const oldVal = totalStakesByCollateral[collateral] || 0n;
2481
+ totalStakesByCollateral[collateral] = oldVal + stakeValue;
2482
+ }
2483
+ }
2484
+ }
2485
+ }
2486
+ // 5) Finally, print aggregated totals
2487
+ logger_1.logger.log("\nAggregated stakes by collateral:");
2488
+ if (Object.keys(totalStakesByCollateral).length === 0) {
2489
+ logger_1.logger.log(" No stakes found or operator not opted into any L1s this way.");
2490
+ }
2491
+ else {
2492
+ for (const [collateralAddr, totalWei] of Object.entries(totalStakesByCollateral)) {
2493
+ // optional: look up decimals for that collateral if you want a float
2494
+ const decimals = 18; // or read from chain
2495
+ const floatAmount = Number(totalWei) / 10 ** decimals;
2496
+ logger_1.logger.log(` Collateral=${collateralAddr} totalStakeWei=${totalWei} => ${floatAmount}`);
2497
+ }
2498
+ }
2499
+ });
2500
+ vaultManagerCmd
2501
+ .command("l1stakes")
2502
+ .description("Show L1 stakes for a given validator manager")
2503
+ .addArgument(argValidatorManagerAddress)
2504
+ .description("Show L1 stakes for a given validator manager")
2505
+ .asyncAction(async (config) => {
2506
+ // TODO: Implement
2507
+ });
2508
+ // --------------------------------------------------
2509
+ // "UpTime" Commands
2510
+ // These commands help with reporting validator uptime to the UptimeTracker contract
2511
+ // They include fetching the signed uptime message from a validator and submitting it to the contract
2512
+ // --------------------------------------------------
2513
+ const uptimeCmd = program
2514
+ .command("uptime")
2515
+ .description("Commands related to validator uptime reporting");
2516
+ uptimeCmd
2517
+ .command("get-validation-uptime-message")
2518
+ .description("Get the validation uptime message for a given validator in the given L1 RPC")
2519
+ .addArgument((0, cliParser_1.ArgURI)("rpcUrl", "RPC URL like 'http(s)://<domain or ip and port>'"))
2520
+ .addArgument((0, cliParser_1.ArgCB58)("blockchainId", "Blockchain ID"))
2521
+ .addArgument((0, cliParser_1.ArgNodeID)())
2522
+ .asyncAction(async (config, rpcUrl, blockchainId, nodeId) => {
2523
+ rpcUrl = rpcUrl + "/ext/bc/" + blockchainId;
2524
+ const opts = program.opts();
2525
+ const client = await (0, client_1.generateClient)(opts.network);
2526
+ await (0, uptime_1.getValidationUptimeMessage)(config.client, rpcUrl, nodeId, config.client.network === "fuji" ? 5 : 1, blockchainId);
2527
+ });
2528
+ uptimeCmd
2529
+ .command('compute-validator-uptime')
2530
+ .addArgument(argUptimeTrackerAddress)
2531
+ .addArgument((0, cliParser_1.ArgHex)("signedUptimeHex", "Signed uptime hex"))
2532
+ .asyncAction({ signer: true }, async (config, uptimeTrackerAddress, signedUptimeHex) => {
2533
+ await (0, uptime_1.computeValidatorUptime)(await config.contracts.UptimeTracker(uptimeTrackerAddress), signedUptimeHex);
2534
+ });
2535
+ // ---- Combined Uptime Reporting Command ----
2536
+ uptimeCmd
2537
+ .command("report-uptime-validator")
2538
+ .description("Gets a validator's signed uptime message and submits it to the UptimeTracker contract.")
2539
+ .addArgument((0, cliParser_1.ArgURI)("rpcUrl", "RPC URL like 'http(s)://<domain or ip and port>'"))
2540
+ .addArgument((0, cliParser_1.ArgCB58)("blockchainId", "The Blockchain ID for which the uptime is being reported"))
2541
+ .addArgument((0, cliParser_1.ArgNodeID)("nodeId", "The NodeID of the validator"))
2542
+ .addArgument(argUptimeTrackerAddress)
2543
+ .asyncAction({ signer: true }, async (config, rpcUrl, blockchainId, nodeId, uptimeTrackerAddress) => {
2544
+ const opts = program.opts();
2545
+ if (!opts.privateKey) {
2546
+ logger_1.logger.error("Error: Private key is required. Use -k or set PK environment variable.");
2547
+ process.exit(1);
2548
+ }
2549
+ rpcUrl = rpcUrl + "/ext/bc/" + blockchainId;
2550
+ await (0, uptime_1.reportAndSubmitValidatorUptime)(config.client, rpcUrl, nodeId, blockchainId, await config.contracts.UptimeTracker(uptimeTrackerAddress));
2551
+ });
2552
+ // ---- Adding new commands for operator uptime ----
2553
+ uptimeCmd
2554
+ .command("compute-operator-uptime")
2555
+ .description("Compute uptime for an operator at a specific epoch")
2556
+ .addArgument(argUptimeTrackerAddress)
2557
+ .addArgument(argOperatorAddress)
2558
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch number"))
2559
+ .asyncAction({ signer: true }, async (config, uptimeTrackerAddress, operator, epoch) => {
2560
+ const opts = program.opts();
2561
+ if (!opts.privateKey) {
2562
+ logger_1.logger.error("Error: Private key is required. Use -k or set PK environment variable.");
2563
+ process.exit(1);
2564
+ }
2565
+ const uptimeTracker = await config.contracts.UptimeTracker(uptimeTrackerAddress);
2566
+ await (0, uptime_1.computeOperatorUptimeAtEpoch)(uptimeTracker, operator, epoch);
2567
+ });
2568
+ uptimeCmd
2569
+ .command("compute-operator-uptime-range")
2570
+ .description("Compute uptime for an operator over a range of epochs (client-side looping)")
2571
+ .addArgument(argUptimeTrackerAddress)
2572
+ .addArgument(argOperatorAddress)
2573
+ .addArgument((0, cliParser_1.ArgNumber)("startEpoch", "Starting epoch number"))
2574
+ .addArgument((0, cliParser_1.ArgNumber)("endEpoch", "Ending epoch number"))
2575
+ .asyncAction({ signer: true }, async (config, uptimeTrackerAddress, operator, startEpoch, endEpoch) => {
2576
+ const opts = program.opts();
2577
+ if (!opts.privateKey) {
2578
+ logger_1.logger.error("Error: Private key is required. Use -k or set PK environment variable.");
2579
+ process.exit(1);
2580
+ }
2581
+ const uptimeTracker = await config.contracts.UptimeTracker(uptimeTrackerAddress);
2582
+ await (0, uptime_1.computeOperatorUptimeForEpochs)(uptimeTracker, operator, startEpoch, endEpoch);
2583
+ });
2584
+ // ---- Read-only commands for uptime data ----
2585
+ uptimeCmd
2586
+ .command("get-validator-uptime")
2587
+ .description("Get the recorded uptime for a validator at a specific epoch")
2588
+ .addArgument(argUptimeTrackerAddress)
2589
+ .addArgument((0, cliParser_1.ArgHex)("validationID", "Validation ID of the validator"))
2590
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch number"))
2591
+ .asyncAction(async (config, uptimeTrackerAddress, validationID, epoch) => {
2592
+ const uptimeTracker = await config.contracts.UptimeTracker(uptimeTrackerAddress);
2593
+ const uptime = await (0, uptime_1.getValidatorUptimeForEpoch)(uptimeTracker, validationID, epoch);
2594
+ logger_1.logger.log(`Validator uptime for epoch ${epoch}: ${uptime.toString()} seconds`);
2595
+ });
2596
+ uptimeCmd
2597
+ .command("check-validator-uptime-set")
2598
+ .description("Check if uptime data is set for a validator at a specific epoch")
2599
+ .addArgument(argUptimeTrackerAddress)
2600
+ .addArgument((0, cliParser_1.ArgHex)("validationID", "Validation ID of the validator"))
2601
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch number"))
2602
+ .asyncAction(async (config, uptimeTrackerAddress, validationID, epoch) => {
2603
+ const uptimeTracker = await config.contracts.UptimeTracker(uptimeTrackerAddress);
2604
+ const isSet = await (0, uptime_1.isValidatorUptimeSetForEpoch)(uptimeTracker, validationID, epoch);
2605
+ logger_1.logger.log(`Validator uptime is ${isSet ? 'set' : 'not set'} for epoch ${epoch}`);
2606
+ });
2607
+ uptimeCmd
2608
+ .command("get-operator-uptime")
2609
+ .description("Get the recorded uptime for an operator at a specific epoch")
2610
+ .addArgument(argUptimeTrackerAddress)
2611
+ .addArgument(argOperatorAddress)
2612
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch number"))
2613
+ .asyncAction(async (config, uptimeTrackerAddress, operator, epoch) => {
2614
+ const uptimeTracker = await config.contracts.UptimeTracker(uptimeTrackerAddress);
2615
+ const uptime = await (0, uptime_1.getOperatorUptimeForEpoch)(uptimeTracker, operator, epoch);
2616
+ logger_1.logger.log(`Operator uptime for epoch ${epoch}: ${uptime.toString()} seconds`);
2617
+ });
2618
+ uptimeCmd
2619
+ .command("check-operator-uptime-set")
2620
+ .description("Check if uptime data is set for an operator at a specific epoch")
2621
+ .addArgument(argUptimeTrackerAddress)
2622
+ .addArgument(argOperatorAddress)
2623
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch number"))
2624
+ .asyncAction(async (config, uptimeTrackerAddress, operator, epoch) => {
2625
+ const uptimeTracker = await config.contracts.UptimeTracker(uptimeTrackerAddress);
2626
+ const isSet = await (0, uptime_1.isOperatorUptimeSetForEpoch)(uptimeTracker, operator, epoch);
2627
+ logger_1.logger.log(`Operator uptime is ${isSet ? 'set' : 'not set'} for epoch ${epoch}`);
2628
+ });
2629
+ uptimeCmd
2630
+ .command("uptime-sync")
2631
+ .description("Report uptime for all validators")
2632
+ .addArgument(argUptimeTrackerAddress)
2633
+ .addArgument(argMiddlewareAddress)
2634
+ .argument("rpcUrl", "RPC URL of the network")
2635
+ .addArgument((0, cliParser_1.ArgCB58)("blockchainId", "The Blockchain ID for which the uptime is being reported"))
2636
+ .addOption(new extra_typings_1.Option("--epoch <epoch>", "Epoch number to check (defaults to current epoch)").argParser(cliParser_1.ParserNumber))
2637
+ .asyncAction({ signer: true }, async (config, uptimeTrackerAddress, middlewareAddress, rpcUrl, blockchainId, options) => {
2638
+ const uptimeTracker = await config.contracts.UptimeTracker(uptimeTrackerAddress);
2639
+ const middlewareSvc = await config.contracts.L1Middleware(middlewareAddress);
2640
+ await (0, uptime_1.uptimeSync)(config.client, uptimeTracker, middlewareSvc, rpcUrl, blockchainId);
2641
+ });
2642
+ /* --------------------------------------------------
2643
+ * REWARDS COMMANDS
2644
+ * -------------------------------------------------- */
2645
+ const rewardsCmd = program
2646
+ .command("rewards")
2647
+ .description("Commands for managing rewards");
2648
+ rewardsCmd
2649
+ .command("distribute")
2650
+ .description("Distribute rewards for a specific epoch")
2651
+ .addArgument(argRewardsAddress)
2652
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch to distribute rewards for"))
2653
+ .addArgument((0, cliParser_1.ArgNumber)("batchSize", "Number of operators to process in this batch"))
2654
+ .asyncAction({ signer: true }, async (config, rewardsAddress, epoch, batchSize) => {
2655
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2656
+ const txHash = await (0, rewards_1.distributeRewards)(rewardsContract, epoch, batchSize);
2657
+ logger_1.logger.log(`Rewards distributed for epoch ${epoch}. tx hash: ${txHash}`);
2658
+ });
2659
+ rewardsCmd
2660
+ .command("claim")
2661
+ .description("Claim rewards for a staker in batch of 64 epochs")
2662
+ .addArgument(argRewardsAddress)
2663
+ .addOption(new extra_typings_1.Option("--recipient <recipient>", "Optional recipient address").argParser(cliParser_1.ParserAddress))
2664
+ .asyncAction({ signer: true }, async (config, rewardsAddress, options) => {
2665
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2666
+ const recipient = options.recipient ?? config.client.account.address;
2667
+ let hashs = [];
2668
+ for (const _ of Array.from({ length: await (0, rewards_1.getRewardsClaimsCount)(rewardsContract, config, 'Staker', config.client.account) })) {
2669
+ hashs.push(await (0, rewards_1.claimRewards)(rewardsContract, recipient));
2670
+ }
2671
+ if (hashs.length === 0) {
2672
+ logger_1.logger.log("No rewards to claim");
2673
+ return;
2674
+ }
2675
+ const logs = await Promise.all(hashs.map(hash => (0, transferUtils_1.getERC20Events)(hash, config)));
2676
+ logs.flat().forEach((log) => {
2677
+ if (log.eventName === "Transfer") {
2678
+ const { from, to, value } = log.args;
2679
+ logger_1.logger.log(`Rewards claimed: ${value.toString()} tokens transferred from ${from} to ${to}`);
2680
+ }
2681
+ });
2682
+ });
2683
+ rewardsCmd
2684
+ .command("claim-operator-fee")
2685
+ .description("Claim operator fees in batch of 64 epochs")
2686
+ .addArgument(argRewardsAddress)
2687
+ .addOption(new extra_typings_1.Option("--recipient <recipient>", "Optional recipient address").argParser(cliParser_1.ParserAddress))
2688
+ .asyncAction({ signer: true }, async (config, rewardsAddress, options) => {
2689
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2690
+ const recipient = options.recipient ?? config.client.account.address;
2691
+ let hashs = [];
2692
+ for (const _ of Array.from({ length: await (0, rewards_1.getRewardsClaimsCount)(rewardsContract, config, 'Operator', config.client.account) })) {
2693
+ hashs.push(await (0, rewards_1.claimOperatorFee)(rewardsContract, recipient));
2694
+ }
2695
+ if (hashs.length === 0) {
2696
+ logger_1.logger.log("No operator fees to claim");
2697
+ return;
2698
+ }
2699
+ const logs = await Promise.all(hashs.map(hash => (0, transferUtils_1.getERC20Events)(hash, config)));
2700
+ logs.flat().forEach((log) => {
2701
+ if (log.eventName === "Transfer") {
2702
+ const { from, to, value } = log.args;
2703
+ logger_1.logger.log(`Rewards claimed: ${value.toString()} tokens transferred from ${from} to ${to}`);
2704
+ }
2705
+ });
2706
+ });
2707
+ rewardsCmd
2708
+ .command("claim-curator-fee")
2709
+ .description("Claim all curator fees in batch of 64 epochs")
2710
+ .addArgument(argRewardsAddress)
2711
+ .addOption(new extra_typings_1.Option("--recipient <recipient>", "Optional recipient address").argParser(cliParser_1.ParserAddress))
2712
+ .asyncAction({ signer: true }, async (config, rewardsAddress, options) => {
2713
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2714
+ const recipient = options.recipient ?? config.client.account.address;
2715
+ let hashs = [];
2716
+ for (const _ of Array.from({ length: await (0, rewards_1.getRewardsClaimsCount)(rewardsContract, config, 'Curator', config.client.account) })) {
2717
+ hashs.push(await (0, rewards_1.claimCuratorFee)(rewardsContract, recipient));
2718
+ }
2719
+ if (hashs.length === 0) {
2720
+ logger_1.logger.log("No curator fees to claim");
2721
+ return;
2722
+ }
2723
+ const logs = await Promise.all(hashs.map(hash => (0, transferUtils_1.getERC20Events)(hash, config)));
2724
+ logs.flat().forEach((log) => {
2725
+ if (log.eventName === "Transfer") {
2726
+ const { from, to, value } = log.args;
2727
+ logger_1.logger.log(`Rewards claimed: ${value.toString()} tokens transferred from ${from} to ${to}`);
2728
+ }
2729
+ });
2730
+ });
2731
+ rewardsCmd
2732
+ .command("claim-protocol-fee")
2733
+ .description("Claim protocol fees (only for protocol owner)")
2734
+ .addArgument(argRewardsAddress)
2735
+ .addOption(new extra_typings_1.Option("--recipient <recipient>", "Optional recipient address").argParser(cliParser_1.ParserAddress))
2736
+ .asyncAction({ signer: true }, async (config, rewardsAddress, options) => {
2737
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2738
+ const recipient = options.recipient ?? config.client.account.address;
2739
+ const hash = await (0, rewards_1.claimProtocolFee)(rewardsContract, recipient);
2740
+ if (!hash) {
2741
+ logger_1.logger.log("No protocol fees to claim");
2742
+ return;
2743
+ }
2744
+ const logs = await (0, transferUtils_1.getERC20Events)(hash, config);
2745
+ logs.forEach((log) => {
2746
+ if (log.eventName === "Transfer") {
2747
+ const { from, to, value } = log.args;
2748
+ logger_1.logger.log(`Rewards claimed: ${value.toString()} tokens transferred from ${from} to ${to}`);
2749
+ }
2750
+ });
2751
+ });
2752
+ rewardsCmd
2753
+ .command("claim-undistributed")
2754
+ .description("Claim undistributed rewards (admin only)")
2755
+ .addArgument(argRewardsAddress)
2756
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch to claim undistributed rewards for"))
2757
+ .addOption(new extra_typings_1.Option("--recipient <recipient>", "Optional recipient address").argParser(cliParser_1.ParserAddress))
2758
+ .asyncAction({ signer: true }, async (config, rewardsAddress, epoch, options) => {
2759
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2760
+ const recipient = options.recipient ?? config.client.account.address;
2761
+ const hash = await (0, rewards_1.claimUndistributedRewards)(rewardsContract, epoch, recipient);
2762
+ if (!hash) {
2763
+ logger_1.logger.log("No undistributed rewards to claim");
2764
+ return;
2765
+ }
2766
+ const logs = await (0, transferUtils_1.getERC20Events)(hash, config);
2767
+ logs.forEach((log) => {
2768
+ if (log.eventName === "Transfer") {
2769
+ const { from, to, value } = log.args;
2770
+ logger_1.logger.log(`Rewards claimed: ${value.toString()} tokens transferred from ${from} to ${to}`);
2771
+ }
2772
+ });
2773
+ });
2774
+ rewardsCmd
2775
+ .command("set-amount")
2776
+ .description("Set rewards amount for epochs")
2777
+ .addArgument(argRewardsAddress)
2778
+ .addArgument((0, cliParser_1.ArgNumber)("startEpoch", "Starting epoch"))
2779
+ .addArgument((0, cliParser_1.ArgNumber)("numberOfEpochs", "Number of epochs"))
2780
+ .argument("rewardsAmount", "Amount of rewards in decimal format")
2781
+ .asyncAction({ signer: true }, async (config, rewardsAddress, startEpoch, numberOfEpochs, rewardsAmount) => {
2782
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2783
+ if (rewardsContract.name !== 'RewardsNativeToken') {
2784
+ throw new Error('Rewards contract is not a RewardsNativeToken');
2785
+ }
2786
+ const tokenAddress = await rewardsContract.read.rewardsToken();
2787
+ const token = await config.contracts.ERC20(tokenAddress);
2788
+ const decimals = await token.read.decimals();
2789
+ const rewardsAmountWei = (0, viem_1.parseUnits)(rewardsAmount, decimals);
2790
+ const amountToApprove = rewardsAmountWei * BigInt(numberOfEpochs);
2791
+ await token.safeWrite.approve([rewardsAddress, amountToApprove], {
2792
+ chain: null,
2793
+ account: config.client.account,
2794
+ });
2795
+ const txHash = await (0, rewards_1.setRewardsAmountForEpochs)(rewardsContract, startEpoch, numberOfEpochs, rewardsAmountWei);
2796
+ logger_1.logger.log(`setRewardsAmountForEpochs tx hash: ${txHash}`);
2797
+ });
2798
+ rewardsCmd
2799
+ .command("set-bips-collateral-class")
2800
+ .description("Set rewards bips for collateral class")
2801
+ .addArgument(argRewardsAddress)
2802
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClass", "Collateral class ID"))
2803
+ .addArgument((0, cliParser_1.ArgNumber)("bips", "Bips in basis points (100 = 1%)"))
2804
+ .asyncAction({ signer: true }, async (config, rewardsAddress, collateralClass, bips) => {
2805
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2806
+ const hash = await (0, rewards_1.setRewardsBipsForCollateralClass)(rewardsContract, collateralClass, bips);
2807
+ logger_1.logger.log(`setRewardsBipsForCollateralClass tx hash: ${hash}`);
2808
+ });
2809
+ rewardsCmd
2810
+ .command("set-min-uptime")
2811
+ .description("Set minimum required uptime for rewards eligibility")
2812
+ .addArgument(argRewardsAddress)
2813
+ .addArgument((0, cliParser_1.ArgBigInt)("minUptime", "Minimum uptime in seconds"))
2814
+ .asyncAction({ signer: true }, async (config, rewardsAddress, minUptime) => {
2815
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2816
+ const hash = await (0, rewards_1.setMinRequiredUptime)(rewardsContract, minUptime);
2817
+ logger_1.logger.log(`setMinRequiredUptime tx hash: ${hash}`);
2818
+ });
2819
+ rewardsCmd
2820
+ .command("set-protocol-owner")
2821
+ .description("Set protocol owner (DEFAULT_ADMIN_ROLE only)")
2822
+ .addArgument(argRewardsAddress)
2823
+ .addArgument((0, cliParser_1.ArgAddress)("newOwner", "New protocol owner address"))
2824
+ .asyncAction({ signer: true }, async (config, rewardsAddress, newOwner) => {
2825
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2826
+ const hash = await (0, rewards_1.setProtocolOwner)(rewardsContract, newOwner);
2827
+ logger_1.logger.log(`setProtocolOwner tx hash: ${hash}`);
2828
+ });
2829
+ rewardsCmd
2830
+ .command("update-protocol-fee")
2831
+ .description("Update protocol fee")
2832
+ .addArgument(argRewardsAddress)
2833
+ .addArgument((0, cliParser_1.ArgNumber)("newFee", "New fee in basis points (100 = 1%)"))
2834
+ .asyncAction({ signer: true }, async (config, rewardsAddress, newFee) => {
2835
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2836
+ const hash = await (0, rewards_1.updateProtocolFee)(rewardsContract, newFee);
2837
+ logger_1.logger.log(`updateProtocolFee tx hash: ${hash}`);
2838
+ });
2839
+ rewardsCmd
2840
+ .command("update-operator-fee")
2841
+ .description("Update operator fee")
2842
+ .addArgument(argRewardsAddress)
2843
+ .addArgument((0, cliParser_1.ArgNumber)("newFee", "New fee in basis points (100 = 1%)"))
2844
+ .asyncAction({ signer: true }, async (config, rewardsAddress, newFee) => {
2845
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2846
+ const hash = await (0, rewards_1.updateOperatorFee)(rewardsContract, newFee);
2847
+ logger_1.logger.log(`updateOperatorFee tx hash: ${hash}`);
2848
+ });
2849
+ rewardsCmd
2850
+ .command("update-curator-fee")
2851
+ .description("Update curator fee")
2852
+ .addArgument(argRewardsAddress)
2853
+ .addArgument((0, cliParser_1.ArgNumber)("newFee", "New fee in basis points (100 = 1%)"))
2854
+ .asyncAction({ signer: true }, async (config, rewardsAddress, newFee) => {
2855
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2856
+ const hash = await (0, rewards_1.updateCuratorFee)(rewardsContract, newFee);
2857
+ logger_1.logger.log(`updateCuratorFee tx hash: ${hash}`);
2858
+ });
2859
+ rewardsCmd
2860
+ .command("update-all-fees")
2861
+ .description("Update all fees at once (protocol, operator, curator)")
2862
+ .addArgument(argRewardsAddress)
2863
+ .addArgument((0, cliParser_1.ArgNumber)("protocolFee", "New protocol fee in basis points (100 = 1%)"))
2864
+ .addArgument((0, cliParser_1.ArgNumber)("operatorFee", "New operator fee in basis points (100 = 1%)"))
2865
+ .addArgument((0, cliParser_1.ArgNumber)("curatorFee", "New curator fee in basis points (100 = 1%)"))
2866
+ .asyncAction({ signer: true }, async (config, rewardsAddress, protocolFee, operatorFee, curatorFee) => {
2867
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2868
+ const hash = await (0, rewards_1.updateAllFees)(rewardsContract, protocolFee, operatorFee, curatorFee);
2869
+ logger_1.logger.log(`updateAllFees tx hash: ${hash}`);
2870
+ });
2871
+ rewardsCmd
2872
+ .command("get-epoch-rewards")
2873
+ .description("Get rewards amount for a specific epoch")
2874
+ .addArgument(argRewardsAddress)
2875
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch to query"))
2876
+ .asyncAction(async (config, rewardsAddress, epoch) => {
2877
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2878
+ await (0, rewards_1.getEpochRewards)(rewardsContract, epoch);
2879
+ });
2880
+ rewardsCmd
2881
+ .command("get-operator-shares")
2882
+ .description("Get operator shares for a specific epoch")
2883
+ .addArgument(argRewardsAddress)
2884
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch to query"))
2885
+ .addArgument(argOperatorAddress)
2886
+ .asyncAction(async (config, rewardsAddress, epoch, operator) => {
2887
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2888
+ await (0, rewards_1.getOperatorShares)(rewardsContract, epoch, operator);
2889
+ });
2890
+ rewardsCmd
2891
+ .command("get-vault-shares")
2892
+ .description("Get vault shares for a specific epoch")
2893
+ .addArgument(argRewardsAddress)
2894
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch to query"))
2895
+ .addArgument(argVaultAddress)
2896
+ .asyncAction(async (config, rewardsAddress, epoch, vault) => {
2897
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2898
+ await (0, rewards_1.getVaultShares)(rewardsContract, epoch, vault);
2899
+ });
2900
+ rewardsCmd
2901
+ .command("get-curator-shares")
2902
+ .description("Get curator shares for a specific epoch")
2903
+ .addArgument(argRewardsAddress)
2904
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch to query"))
2905
+ .addArgument((0, cliParser_1.ArgAddress)("curator", "Curator address"))
2906
+ .asyncAction(async (config, rewardsAddress, epoch, curator) => {
2907
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2908
+ await (0, rewards_1.getCuratorShares)(rewardsContract, epoch, curator);
2909
+ });
2910
+ rewardsCmd
2911
+ .command("get-protocol-rewards")
2912
+ .description("Get protocol rewards for a token")
2913
+ .addArgument(argRewardsAddress)
2914
+ .addArgument((0, cliParser_1.ArgAddress)("token", "Token address"))
2915
+ .asyncAction(async (config, rewardsAddress, token) => {
2916
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2917
+ await (0, rewards_1.getProtocolRewards)(rewardsContract);
2918
+ });
2919
+ rewardsCmd
2920
+ .command("get-distribution-batch")
2921
+ .description("Get distribution batch status for an epoch")
2922
+ .addArgument(argRewardsAddress)
2923
+ .addArgument((0, cliParser_1.ArgNumber)("epoch", "Epoch to query"))
2924
+ .asyncAction(async (config, rewardsAddress, epoch) => {
2925
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2926
+ await (0, rewards_1.getDistributionBatch)(rewardsContract, epoch);
2927
+ });
2928
+ rewardsCmd
2929
+ .command("get-fees-config")
2930
+ .description("Get current fees configuration")
2931
+ .addArgument(argRewardsAddress)
2932
+ .asyncAction(async (config, rewardsAddress) => {
2933
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2934
+ await (0, rewards_1.getFeesConfiguration)(rewardsContract);
2935
+ });
2936
+ rewardsCmd
2937
+ .command("get-bips-collateral-class")
2938
+ .description("Get rewards bips for collateral class")
2939
+ .addArgument(argRewardsAddress)
2940
+ .addArgument((0, cliParser_1.ArgBigInt)("collateralClass", "Collateral class ID"))
2941
+ .asyncAction(async (config, rewardsAddress, collateralClass) => {
2942
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2943
+ await (0, rewards_1.getRewardsBipsForCollateralClass)(rewardsContract, collateralClass);
2944
+ });
2945
+ rewardsCmd
2946
+ .command("get-min-uptime")
2947
+ .description("Get minimum required uptime for rewards eligibility")
2948
+ .addArgument(argRewardsAddress)
2949
+ .asyncAction(async (config, rewardsAddress) => {
2950
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2951
+ await (0, rewards_1.getMinRequiredUptime)(rewardsContract);
2952
+ });
2953
+ rewardsCmd
2954
+ .command("get-last-claimed-staker")
2955
+ .description("Get last claimed epoch for a staker")
2956
+ .addArgument(argRewardsAddress)
2957
+ .addArgument((0, cliParser_1.ArgAddress)("staker", "Staker address"))
2958
+ .addArgument(argRewardTokenAddress)
2959
+ .asyncAction(async (config, rewardsAddress, staker, rewardToken) => {
2960
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2961
+ await (0, rewards_1.getLastEpochClaimedStaker)(rewardsContract, staker);
2962
+ });
2963
+ rewardsCmd
2964
+ .command("get-last-claimed-operator")
2965
+ .description("Get last claimed epoch for an operator")
2966
+ .addArgument(argRewardsAddress)
2967
+ .addArgument(argOperatorAddress)
2968
+ .addArgument(argRewardTokenAddress)
2969
+ .asyncAction(async (config, rewardsAddress, operator, rewardToken) => {
2970
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2971
+ await (0, rewards_1.getLastEpochClaimedOperator)(rewardsContract, operator);
2972
+ });
2973
+ rewardsCmd
2974
+ .command("get-last-claimed-curator")
2975
+ .description("Get last claimed epoch for a curator")
2976
+ .addArgument(argRewardsAddress)
2977
+ .addArgument((0, cliParser_1.ArgAddress)("curator", "Curator address"))
2978
+ .addArgument(argRewardTokenAddress)
2979
+ .asyncAction(async (config, rewardsAddress, curator, rewardToken) => {
2980
+ const rewardsContract = await config.contracts.RewardsNativeToken(rewardsAddress);
2981
+ await (0, rewards_1.getLastEpochClaimedCurator)(rewardsContract, curator);
2982
+ });
2983
+ (0, keyStore_1.buildCommands)(program
2984
+ .command("key")
2985
+ .description("Manage the cli keystore (advanced users can use pass directly)"));
2986
+ function printIndentedHelp(cmd, indent = 0) {
2987
+ const pad = " ".repeat(indent);
2988
+ let newLineToLog = false;
2989
+ let hasSubCmds = false;
2990
+ cmd.commands.forEach((sub) => {
2991
+ const args = sub.args?.map(a => `<${a}>`).join(" ");
2992
+ const desc = sub.description() ? sub.description() : "";
2993
+ console.log(`${newLineToLog ? "\n" : ""}${pad}${sub.name()} ${args.padEnd(31 - sub.name().length)} ${desc}`);
2994
+ if (sub.commands.length > 0) {
2995
+ newLineToLog = printIndentedHelp(sub, indent + 2);
2996
+ hasSubCmds = true;
2997
+ }
2998
+ });
2999
+ if (!hasSubCmds || hasSubCmds && !newLineToLog)
3000
+ newLineToLog = true;
3001
+ return newLineToLog;
3002
+ }
3003
+ const accessControlCmd = program
3004
+ .command("access-control")
3005
+ .description("Commands for managing access control");
3006
+ accessControlCmd
3007
+ .command("grant-role")
3008
+ .description("Grant a role to an account")
3009
+ .addArgument(argAccessControlAddress)
3010
+ .argument("role", "Role hash or name case unsensitive without '()'")
3011
+ .addArgument((0, cliParser_1.ArgAddress)("account", "Account address to grant the role to"))
3012
+ .asyncAction({ signer: true }, async (config, contractAddress, role, account) => {
3013
+ const accessControl = await config.contracts.AccessControl(contractAddress);
3014
+ if (!await (0, accessControl_1.isAccessControl)(accessControl)) {
3015
+ throw new Error("Contract does not implement AccessControl interface");
3016
+ }
3017
+ const txHash = await (0, accessControl_1.grantRole)(accessControl, role, account);
3018
+ logger_1.logger.log(`Role granted. tx hash: ${txHash}`);
3019
+ });
3020
+ accessControlCmd
3021
+ .command("revoke-role")
3022
+ .description("Revoke a role from an account")
3023
+ .addArgument(argAccessControlAddress)
3024
+ .argument("role", "Role hash or name case unsensitive")
3025
+ .addArgument((0, cliParser_1.ArgAddress)("account", "Account address to revoke the role from"))
3026
+ .asyncAction({ signer: true }, async (config, contractAddress, role, account) => {
3027
+ const accessControl = await config.contracts.AccessControl(contractAddress);
3028
+ if (!await (0, accessControl_1.isAccessControl)(accessControl)) {
3029
+ throw new Error("Contract does not implement AccessControl interface");
3030
+ }
3031
+ const txHash = await (0, accessControl_1.revokeRole)(accessControl, role, account);
3032
+ logger_1.logger.log(`Role revoked. tx hash: ${txHash}`);
3033
+ });
3034
+ accessControlCmd
3035
+ .command("has-role")
3036
+ .description("Check if an account has a specific role")
3037
+ .addArgument(argAccessControlAddress)
3038
+ .argument("role", "Role hash or name case unsensitive")
3039
+ .addArgument((0, cliParser_1.ArgAddress)("account", "Account address to check"))
3040
+ .asyncAction(async (config, contractAddress, role, account) => {
3041
+ const accessControl = await config.contracts.AccessControl(contractAddress);
3042
+ if (!await (0, accessControl_1.isAccessControl)(accessControl)) {
3043
+ throw new Error("Contract does not implement AccessControl interface");
3044
+ }
3045
+ const hasRoleResult = await (0, accessControl_1.hasRole)(accessControl, role, account);
3046
+ logger_1.logger.log(`Account ${account} has role ${role}: ${hasRoleResult}`);
3047
+ });
3048
+ accessControlCmd
3049
+ .command("get-role-admin")
3050
+ .description("Get the admin role that controls a specific role")
3051
+ .addArgument(argAccessControlAddress)
3052
+ .argument("role", "Role hash or name case unsensitive")
3053
+ .asyncAction(async (config, contractAddress, role) => {
3054
+ const accessControl = await config.contracts.AccessControl(contractAddress);
3055
+ if (!await (0, accessControl_1.isAccessControl)(accessControl)) {
3056
+ throw new Error("Contract does not implement AccessControl interface");
3057
+ }
3058
+ const adminRole = await (0, accessControl_1.getRoleAdmin)(accessControl, role);
3059
+ logger_1.logger.log(`Admin role for role ${role} is: ${adminRole}`);
3060
+ });
3061
+ const ledgerCmd = program
3062
+ .command("ledger")
3063
+ .description("Commands for ledger");
3064
+ ledgerCmd
3065
+ .command("addresses")
3066
+ .description("Get ledger addresses")
3067
+ .asyncAction(async () => {
3068
+ const opts = program.opts();
3069
+ const client = await (0, client_1.generateClient)(opts.network, 'ledger');
3070
+ logger_1.logger.log(client.addresses);
3071
+ });
3072
+ ledgerCmd
3073
+ .command('fix-usb-rules')
3074
+ .description('Fix ledger usb rules on linux')
3075
+ .asyncAction(async (config) => {
3076
+ logger_1.logger.log("Fixing ledger usb rules...");
3077
+ try {
3078
+ // Execute system command to fix ledger usb rules (https://github.com/LedgerHQ/ledger-live-desktop/issues/2873#issuecomment-674844905)
3079
+ const result = (0, child_process_1.execSync)('wget -q -O - https://raw.githubusercontent.com/LedgerHQ/udev-rules/master/add_udev_rules.sh | sudo bash');
3080
+ logger_1.logger.log(result.toString());
3081
+ }
3082
+ catch (error) {
3083
+ logger_1.logger.error("Failed to fix ledger usb rules");
3084
+ logger_1.logger.error(error);
3085
+ }
3086
+ });
3087
+ const safeCmd = program
3088
+ .command("safe")
3089
+ .description("Commands for safe");
3090
+ safeCmd
3091
+ .command("nonce")
3092
+ .description("Get safe nonce")
3093
+ .addArgument((0, cliParser_1.ArgAddress)("safeAddress", "Address of the safe"))
3094
+ .asyncAction(async (config, safeAddress) => {
3095
+ logger_1.logger.log((await config.client.safe.getNonce()).toString());
3096
+ });
3097
+ safeCmd
3098
+ .command("get-role")
3099
+ .description("Get user role in the safe")
3100
+ .addOption((0, cliParser_1.OptAddress)("--account <account>", "Account address to check"))
3101
+ .asyncAction({ signer: true }, async (config, options) => {
3102
+ const addressToCheck = options.account || config.client.account.address;
3103
+ const owners = await config.client.safe.getOwners();
3104
+ const delegates = await config.client.safe.apiKit.getSafeDelegates({ safeAddress: program.opts().safe });
3105
+ if (owners.find(owner => owner.toLowerCase() === addressToCheck.toLowerCase())) {
3106
+ logger_1.logger.log("Owner");
3107
+ }
3108
+ else if (delegates.results.find(delegate => delegate.delegate.toLowerCase() === addressToCheck.toLowerCase())) {
3109
+ logger_1.logger.log("Delegate");
3110
+ }
3111
+ else {
3112
+ logger_1.logger.log("No role");
3113
+ }
3114
+ });
3115
+ program.
3116
+ command('create-network', { hidden: true })
3117
+ .description('Create a new network')
3118
+ .argument('chainName', 'Name of the chain')
3119
+ .argument('genesisFile', 'Path to the genesis file')
3120
+ .option('--vm-id <vmId>', 'subnet-evm custom id')
3121
+ .asyncAction({ signer: true }, async (config, chainName, genesisFile, options) => {
3122
+ const subnetId = await (0, pChainUtils_1.createSubnet)({ client: config.client });
3123
+ const genesisData = (0, fs_1.readFileSync)(genesisFile).toString('utf-8');
3124
+ const chainId = await (0, pChainUtils_1.createChain)({
3125
+ client: config.client,
3126
+ chainName,
3127
+ subnetId,
3128
+ genesisData,
3129
+ SubnetEVMId: options.vmId
3130
+ });
3131
+ logger_1.logger.log(`Network created:`);
3132
+ logger_1.logger.log(` Chain ID: ${chainId}`);
3133
+ logger_1.logger.log(` Subnet ID: ${subnetId}`);
3134
+ logger_1.logger.addData('network', { chainId, subnetId });
3135
+ });
3136
+ program
3137
+ .command('subnet-to-l1', { hidden: true })
3138
+ .description('Convert a subnet to L1')
3139
+ .addArgument((0, cliParser_1.ArgCB58)('subnetId', 'Subnet ID of the subnet'))
3140
+ .addArgument((0, cliParser_1.ArgCB58)('chainId', 'Chain ID of the subnet'))
3141
+ .addArgument((0, cliParser_1.ArgAddress)('validatorManagerAddress', 'Validator manager of the subnet'))
3142
+ .addArgument((0, cliParser_1.ArgCB58)('vmcChainId', 'Validator Manager Contract Chain ID'))
3143
+ .addOption(new extra_typings_1.Option('--validatorConfig <validatorConfig>', 'Validator config file path (json)').default([]).argParser((0, cliParser_1.collectMultiple)(String)).makeOptionMandatory())
3144
+ .addOption((0, cliParser_1.OptHex)('--convertTx <convertTx>', 'Existing convert transaction hash to reuse'))
3145
+ .addOption(new extra_typings_1.Option('--init-vmc', 'Initialize the VMC before conversion'))
3146
+ .asyncAction({ signer: true }, async (config, subnetId, chainId, validatorManagerAddress, vmcChainId, options) => {
3147
+ // const validatorManager = await config.contracts.ValidatorManager(validatorManagerAddress)
3148
+ await (0, pChainUtils_1.convertSubnetToL1)({ client: config.client, subnetId, chainId, validatorManager: validatorManagerAddress, validatorManagerBlockchainID: vmcChainId, validators: options.validatorConfig.map(v => JSON.parse((0, fs_1.readFileSync)(v).toString('utf-8'))), convertTx: options.convertTx, init: options.initVmc });
3149
+ });
3150
+ program
3151
+ .command("help-all")
3152
+ .description("Display help for all commands and sub-commands")
3153
+ .action(() => {
3154
+ console.log(`Suzaku CLI - version ${program.version()}`);
3155
+ console.log(program.description());
3156
+ console.log("Commands:\n");
3157
+ printIndentedHelp(program);
3158
+ });
3159
+ program
3160
+ .command("completion install")
3161
+ .description("Install autocompletion for Bash/Zsh")
3162
+ .action(() => (0, autoCompletion_1.installCompletion)(program));
3163
+ program
3164
+ .command("__complete")
3165
+ .description("internal completion helper")
3166
+ .option("--line <line>")
3167
+ .action(({ line }) => {
3168
+ line = line || "";
3169
+ const parts = line.trim().split(/\s+/).slice(1);
3170
+ let node = program;
3171
+ for (const part of parts) {
3172
+ const found = node.commands.find(c => c.name() === part);
3173
+ if (!found)
3174
+ break;
3175
+ node = found;
3176
+ }
3177
+ const suggestions = node.commands.map(c => c.name());
3178
+ console.log(suggestions.join(" "));
3179
+ });
3180
+ program.parse(process.argv);
3181
+ }
3182
+ main();
3183
+ //# sourceMappingURL=cli.js.map