genlayer-js 0.18.4 → 0.18.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/CLAUDE.md +66 -0
- package/README.md +52 -1
- package/dist/chains/index.cjs +2 -2
- package/dist/chains/index.d.cts +2 -2
- package/dist/chains/index.d.ts +2 -2
- package/dist/chains/index.js +1 -1
- package/dist/{chains-BIe_Q0mF.d.cts → chains-B7B7UXdn.d.cts} +6 -2
- package/dist/{chains-BIe_Q0mF.d.ts → chains-B7B7UXdn.d.ts} +6 -2
- package/dist/{chunk-NO75TOQL.js → chunk-KVHGQTAI.js} +539 -4
- package/dist/{chunk-SMGWE7OH.cjs → chunk-QAAO2WJL.cjs} +540 -5
- package/dist/index-3leEwFoq.d.cts +1389 -0
- package/dist/index-BBh1NZjP.d.ts +1389 -0
- package/dist/{index-C5zeayBB.d.cts → index-BVDASTaU.d.cts} +1 -1
- package/dist/{index-BpFWfpio.d.ts → index-ucNO2REF.d.ts} +1 -1
- package/dist/index.cjs +551 -38
- package/dist/index.d.cts +17 -5
- package/dist/index.d.ts +17 -5
- package/dist/index.js +528 -15
- package/dist/types/index.cjs +2 -2
- package/dist/types/index.d.cts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +1 -1
- package/package.json +1 -1
- package/src/abi/index.ts +1 -0
- package/src/abi/staking.ts +525 -0
- package/src/chains/localnet.ts +2 -1
- package/src/chains/studionet.ts +1 -0
- package/src/chains/testnetAsimov.ts +10 -3
- package/src/client/client.ts +17 -15
- package/src/index.ts +1 -0
- package/src/staking/actions.ts +609 -0
- package/src/staking/index.ts +2 -0
- package/src/staking/utils.ts +22 -0
- package/src/types/chains.ts +6 -2
- package/src/types/clients.ts +6 -6
- package/src/types/index.ts +1 -0
- package/src/types/staking.ts +228 -0
- package/tsconfig.vitest-temp.json +41 -0
- package/dist/index-B2AY6_eD.d.ts +0 -407
- package/dist/index-BYma5s90.d.cts +0 -407
- /package/dist/{chunk-FPZNF3JH.cjs → chunk-W4V73RPN.cjs} +0 -0
- /package/dist/{chunk-47QDX7IX.js → chunk-ZHBOSLFN.js} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as viem from 'viem';
|
|
2
2
|
import { Account, Address, Hex } from 'viem';
|
|
3
|
-
import { G as GenLayerChain } from './chains-
|
|
4
|
-
import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement } from './index-
|
|
3
|
+
import { G as GenLayerChain } from './chains-B7B7UXdn.cjs';
|
|
4
|
+
import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement, S as STAKING_ABI, V as VALIDATOR_WALLET_ABI } from './index-3leEwFoq.cjs';
|
|
5
5
|
import * as abitype from 'abitype';
|
|
6
6
|
import * as viem__types_types_authorization from 'viem/_types/types/authorization';
|
|
7
7
|
import * as viem_accounts from 'viem/accounts';
|
|
8
|
-
export { i as chains } from './index-
|
|
8
|
+
export { i as chains } from './index-BVDASTaU.cjs';
|
|
9
9
|
|
|
10
10
|
interface ClientConfig {
|
|
11
11
|
chain?: {
|
|
@@ -88,10 +88,22 @@ declare namespace tx {
|
|
|
88
88
|
declare const calldata: typeof cd;
|
|
89
89
|
declare const transactions: typeof tx;
|
|
90
90
|
|
|
91
|
+
declare const index_STAKING_ABI: typeof STAKING_ABI;
|
|
92
|
+
declare const index_VALIDATOR_WALLET_ABI: typeof VALIDATOR_WALLET_ABI;
|
|
91
93
|
declare const index_calldata: typeof calldata;
|
|
92
94
|
declare const index_transactions: typeof transactions;
|
|
93
95
|
declare namespace index {
|
|
94
|
-
export { index_calldata as calldata, index_transactions as transactions };
|
|
96
|
+
export { index_STAKING_ABI as STAKING_ABI, index_VALIDATOR_WALLET_ABI as VALIDATOR_WALLET_ABI, index_calldata as calldata, index_transactions as transactions };
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Parse staking amount. Use "gen" suffix for GEN tokens (e.g. "42gen"),
|
|
101
|
+
* otherwise value is treated as wei (e.g. "42000000000000000000" = 42 GEN).
|
|
102
|
+
*/
|
|
103
|
+
declare function parseStakingAmount(amount: string | bigint): bigint;
|
|
104
|
+
/**
|
|
105
|
+
* Format bigint amount to human-readable GEN string.
|
|
106
|
+
*/
|
|
107
|
+
declare function formatStakingAmount(amount: bigint): string;
|
|
108
|
+
|
|
109
|
+
export { index as abi, createAccount, createClient, decodeInputData, decodeLocalnetTransaction, decodeTransaction, formatStakingAmount, generatePrivateKey, parseStakingAmount, simplifyTransactionReceipt };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as viem from 'viem';
|
|
2
2
|
import { Account, Address, Hex } from 'viem';
|
|
3
|
-
import { G as GenLayerChain } from './chains-
|
|
4
|
-
import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement } from './index-
|
|
3
|
+
import { G as GenLayerChain } from './chains-B7B7UXdn.js';
|
|
4
|
+
import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement, S as STAKING_ABI, V as VALIDATOR_WALLET_ABI } from './index-BBh1NZjP.js';
|
|
5
5
|
import * as abitype from 'abitype';
|
|
6
6
|
import * as viem__types_types_authorization from 'viem/_types/types/authorization';
|
|
7
7
|
import * as viem_accounts from 'viem/accounts';
|
|
8
|
-
export { i as chains } from './index-
|
|
8
|
+
export { i as chains } from './index-ucNO2REF.js';
|
|
9
9
|
|
|
10
10
|
interface ClientConfig {
|
|
11
11
|
chain?: {
|
|
@@ -88,10 +88,22 @@ declare namespace tx {
|
|
|
88
88
|
declare const calldata: typeof cd;
|
|
89
89
|
declare const transactions: typeof tx;
|
|
90
90
|
|
|
91
|
+
declare const index_STAKING_ABI: typeof STAKING_ABI;
|
|
92
|
+
declare const index_VALIDATOR_WALLET_ABI: typeof VALIDATOR_WALLET_ABI;
|
|
91
93
|
declare const index_calldata: typeof calldata;
|
|
92
94
|
declare const index_transactions: typeof transactions;
|
|
93
95
|
declare namespace index {
|
|
94
|
-
export { index_calldata as calldata, index_transactions as transactions };
|
|
96
|
+
export { index_STAKING_ABI as STAKING_ABI, index_VALIDATOR_WALLET_ABI as VALIDATOR_WALLET_ABI, index_calldata as calldata, index_transactions as transactions };
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Parse staking amount. Use "gen" suffix for GEN tokens (e.g. "42gen"),
|
|
101
|
+
* otherwise value is treated as wei (e.g. "42000000000000000000" = 42 GEN).
|
|
102
|
+
*/
|
|
103
|
+
declare function parseStakingAmount(amount: string | bigint): bigint;
|
|
104
|
+
/**
|
|
105
|
+
* Format bigint amount to human-readable GEN string.
|
|
106
|
+
*/
|
|
107
|
+
declare function formatStakingAmount(amount: bigint): string;
|
|
108
|
+
|
|
109
|
+
export { index as abi, createAccount, createClient, decodeInputData, decodeLocalnetTransaction, decodeTransaction, formatStakingAmount, generatePrivateKey, parseStakingAmount, simplifyTransactionReceipt };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
+
STAKING_ABI,
|
|
3
|
+
VALIDATOR_WALLET_ABI,
|
|
2
4
|
chains_exports,
|
|
3
5
|
localnet,
|
|
4
6
|
studionet,
|
|
5
7
|
testnetAsimov
|
|
6
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-KVHGQTAI.js";
|
|
7
9
|
import {
|
|
8
10
|
CalldataAddress,
|
|
9
11
|
isDecidedState,
|
|
@@ -11,7 +13,7 @@ import {
|
|
|
11
13
|
transactionsStatusNameToNumber,
|
|
12
14
|
transactionsStatusNumberToName,
|
|
13
15
|
voteTypeNumberToName
|
|
14
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ZHBOSLFN.js";
|
|
15
17
|
import {
|
|
16
18
|
__export
|
|
17
19
|
} from "./chunk-MLKGABMK.js";
|
|
@@ -413,6 +415,8 @@ import { fromHex, toHex as toHex3, zeroAddress, encodeFunctionData, parseEventLo
|
|
|
413
415
|
// src/abi/index.ts
|
|
414
416
|
var abi_exports = {};
|
|
415
417
|
__export(abi_exports, {
|
|
418
|
+
STAKING_ABI: () => STAKING_ABI,
|
|
419
|
+
VALIDATOR_WALLET_ABI: () => VALIDATOR_WALLET_ABI,
|
|
416
420
|
calldata: () => calldata,
|
|
417
421
|
transactions: () => transactions
|
|
418
422
|
});
|
|
@@ -681,13 +685,13 @@ var contractActions = (client, publicClient) => {
|
|
|
681
685
|
}
|
|
682
686
|
};
|
|
683
687
|
};
|
|
684
|
-
var validateAccount = (
|
|
685
|
-
if (!
|
|
688
|
+
var validateAccount = (Account4) => {
|
|
689
|
+
if (!Account4) {
|
|
686
690
|
throw new Error(
|
|
687
691
|
"No account set. Configure the client with an account or pass an account to this function."
|
|
688
692
|
);
|
|
689
693
|
}
|
|
690
|
-
return
|
|
694
|
+
return Account4;
|
|
691
695
|
};
|
|
692
696
|
var _encodeAddTransactionData = ({
|
|
693
697
|
client,
|
|
@@ -1212,6 +1216,509 @@ function walletActions(client) {
|
|
|
1212
1216
|
};
|
|
1213
1217
|
}
|
|
1214
1218
|
|
|
1219
|
+
// src/staking/actions.ts
|
|
1220
|
+
import { getContract, decodeEventLog, toHex as toHex4, encodeFunctionData as encodeFunctionData2, BaseError, ContractFunctionRevertedError } from "viem";
|
|
1221
|
+
|
|
1222
|
+
// src/staking/utils.ts
|
|
1223
|
+
import { parseEther, formatEther } from "viem";
|
|
1224
|
+
function parseStakingAmount(amount) {
|
|
1225
|
+
if (typeof amount === "bigint") return amount;
|
|
1226
|
+
const trimmed = amount.trim();
|
|
1227
|
+
const lower = trimmed.toLowerCase();
|
|
1228
|
+
if (lower.endsWith("gen")) {
|
|
1229
|
+
return parseEther(lower.slice(0, -3).trim());
|
|
1230
|
+
}
|
|
1231
|
+
return BigInt(trimmed);
|
|
1232
|
+
}
|
|
1233
|
+
function formatStakingAmount(amount) {
|
|
1234
|
+
return `${formatEther(amount)} GEN`;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
// src/staking/actions.ts
|
|
1238
|
+
var FALLBACK_GAS = 1000000n;
|
|
1239
|
+
var GAS_BUFFER_MULTIPLIER = 2n;
|
|
1240
|
+
function extractRevertReason(err) {
|
|
1241
|
+
if (err instanceof BaseError) {
|
|
1242
|
+
const revertError = err.walk((e) => e instanceof ContractFunctionRevertedError);
|
|
1243
|
+
if (revertError instanceof ContractFunctionRevertedError) {
|
|
1244
|
+
return revertError.data?.errorName || revertError.reason || "Unknown reason";
|
|
1245
|
+
}
|
|
1246
|
+
if (err.shortMessage) return err.shortMessage;
|
|
1247
|
+
}
|
|
1248
|
+
if (err instanceof Error) return err.message;
|
|
1249
|
+
return "Unknown reason";
|
|
1250
|
+
}
|
|
1251
|
+
var stakingActions = (client, publicClient) => {
|
|
1252
|
+
const executeWrite = async (options) => {
|
|
1253
|
+
if (!client.account) {
|
|
1254
|
+
throw new Error("Account is required for write operations. Initialize client with a wallet account.");
|
|
1255
|
+
}
|
|
1256
|
+
const account = client.account;
|
|
1257
|
+
try {
|
|
1258
|
+
await publicClient.call({
|
|
1259
|
+
account,
|
|
1260
|
+
to: options.to,
|
|
1261
|
+
data: options.data,
|
|
1262
|
+
value: options.value
|
|
1263
|
+
});
|
|
1264
|
+
} catch (err) {
|
|
1265
|
+
const revertReason = extractRevertReason(err);
|
|
1266
|
+
throw new Error(`Transaction would revert: ${revertReason}`);
|
|
1267
|
+
}
|
|
1268
|
+
let gasLimit = options.gas;
|
|
1269
|
+
if (!gasLimit) {
|
|
1270
|
+
try {
|
|
1271
|
+
const estimated = await publicClient.estimateGas({
|
|
1272
|
+
account,
|
|
1273
|
+
to: options.to,
|
|
1274
|
+
data: options.data,
|
|
1275
|
+
value: options.value
|
|
1276
|
+
});
|
|
1277
|
+
gasLimit = estimated * GAS_BUFFER_MULTIPLIER;
|
|
1278
|
+
} catch {
|
|
1279
|
+
gasLimit = FALLBACK_GAS;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
const nonce = await publicClient.getTransactionCount({ address: account.address });
|
|
1283
|
+
const txRequest = await publicClient.prepareTransactionRequest({
|
|
1284
|
+
account,
|
|
1285
|
+
to: options.to,
|
|
1286
|
+
data: options.data,
|
|
1287
|
+
value: options.value,
|
|
1288
|
+
type: "legacy",
|
|
1289
|
+
nonce,
|
|
1290
|
+
gas: gasLimit,
|
|
1291
|
+
chain: client.chain
|
|
1292
|
+
});
|
|
1293
|
+
const signTransaction = account.signTransaction;
|
|
1294
|
+
if (!signTransaction) {
|
|
1295
|
+
throw new Error("Account does not support signing transactions");
|
|
1296
|
+
}
|
|
1297
|
+
const serializedTx = await signTransaction(txRequest);
|
|
1298
|
+
const hash = await publicClient.sendRawTransaction({ serializedTransaction: serializedTx });
|
|
1299
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
1300
|
+
if (receipt.status === "reverted") {
|
|
1301
|
+
let revertReason = "Unknown reason";
|
|
1302
|
+
try {
|
|
1303
|
+
await publicClient.call({
|
|
1304
|
+
account,
|
|
1305
|
+
to: options.to,
|
|
1306
|
+
data: options.data,
|
|
1307
|
+
value: options.value,
|
|
1308
|
+
blockNumber: receipt.blockNumber
|
|
1309
|
+
});
|
|
1310
|
+
const gasUsed = receipt.gasUsed;
|
|
1311
|
+
if (gasUsed >= gasLimit - 1000n) {
|
|
1312
|
+
revertReason = `Out of gas (used ${gasUsed}, limit ${gasLimit})`;
|
|
1313
|
+
} else {
|
|
1314
|
+
revertReason = `Unknown (simulation passes but tx reverts). Gas: ${gasUsed}/${gasLimit}`;
|
|
1315
|
+
}
|
|
1316
|
+
} catch (err) {
|
|
1317
|
+
revertReason = extractRevertReason(err);
|
|
1318
|
+
}
|
|
1319
|
+
throw new Error(`Transaction reverted: ${revertReason} (tx: ${hash})`);
|
|
1320
|
+
}
|
|
1321
|
+
return {
|
|
1322
|
+
transactionHash: receipt.transactionHash,
|
|
1323
|
+
blockNumber: receipt.blockNumber,
|
|
1324
|
+
gasUsed: receipt.gasUsed
|
|
1325
|
+
};
|
|
1326
|
+
};
|
|
1327
|
+
const getStakingAddress = () => {
|
|
1328
|
+
const stakingConfig = client.chain.stakingContract;
|
|
1329
|
+
if (!stakingConfig?.address || stakingConfig.address === "0x0000000000000000000000000000000000000000") {
|
|
1330
|
+
throw new Error("Staking is not supported on studio-based networks. Use testnet-asimov for staking operations.");
|
|
1331
|
+
}
|
|
1332
|
+
return stakingConfig.address;
|
|
1333
|
+
};
|
|
1334
|
+
const getStakingContract = () => {
|
|
1335
|
+
const address = getStakingAddress();
|
|
1336
|
+
return getContract({
|
|
1337
|
+
address,
|
|
1338
|
+
abi: STAKING_ABI,
|
|
1339
|
+
client: { public: publicClient, wallet: client }
|
|
1340
|
+
});
|
|
1341
|
+
};
|
|
1342
|
+
const getReadOnlyStakingContract = () => {
|
|
1343
|
+
const address = getStakingAddress();
|
|
1344
|
+
return getContract({
|
|
1345
|
+
address,
|
|
1346
|
+
abi: STAKING_ABI,
|
|
1347
|
+
client: publicClient
|
|
1348
|
+
});
|
|
1349
|
+
};
|
|
1350
|
+
return {
|
|
1351
|
+
validatorJoin: async (options) => {
|
|
1352
|
+
const amount = parseStakingAmount(options.amount);
|
|
1353
|
+
const stakingAddress = getStakingAddress();
|
|
1354
|
+
const data = options.operator ? encodeFunctionData2({
|
|
1355
|
+
abi: STAKING_ABI,
|
|
1356
|
+
functionName: "validatorJoin",
|
|
1357
|
+
args: [options.operator]
|
|
1358
|
+
}) : encodeFunctionData2({
|
|
1359
|
+
abi: STAKING_ABI,
|
|
1360
|
+
functionName: "validatorJoin"
|
|
1361
|
+
});
|
|
1362
|
+
const result = await executeWrite({ to: stakingAddress, data, value: amount });
|
|
1363
|
+
const receipt = await publicClient.getTransactionReceipt({ hash: result.transactionHash });
|
|
1364
|
+
let validatorWallet;
|
|
1365
|
+
let eventFound = false;
|
|
1366
|
+
for (const log of receipt.logs) {
|
|
1367
|
+
try {
|
|
1368
|
+
const decoded = decodeEventLog({ abi: STAKING_ABI, data: log.data, topics: log.topics });
|
|
1369
|
+
if (decoded.eventName === "ValidatorJoin") {
|
|
1370
|
+
validatorWallet = decoded.args.validator;
|
|
1371
|
+
eventFound = true;
|
|
1372
|
+
break;
|
|
1373
|
+
}
|
|
1374
|
+
} catch {
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
if (!eventFound) {
|
|
1378
|
+
throw new Error(
|
|
1379
|
+
`ValidatorJoin event not found in transaction ${result.transactionHash}. Transaction succeeded but validator wallet address could not be determined.`
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
return {
|
|
1383
|
+
transactionHash: receipt.transactionHash,
|
|
1384
|
+
blockNumber: receipt.blockNumber,
|
|
1385
|
+
gasUsed: receipt.gasUsed,
|
|
1386
|
+
validatorWallet,
|
|
1387
|
+
operator: options.operator || client.account.address,
|
|
1388
|
+
amount: formatStakingAmount(amount),
|
|
1389
|
+
amountRaw: amount
|
|
1390
|
+
};
|
|
1391
|
+
},
|
|
1392
|
+
validatorDeposit: async (options) => {
|
|
1393
|
+
const amount = parseStakingAmount(options.amount);
|
|
1394
|
+
const data = encodeFunctionData2({
|
|
1395
|
+
abi: STAKING_ABI,
|
|
1396
|
+
functionName: "validatorDeposit"
|
|
1397
|
+
});
|
|
1398
|
+
return executeWrite({ to: getStakingAddress(), data, value: amount });
|
|
1399
|
+
},
|
|
1400
|
+
validatorExit: async (options) => {
|
|
1401
|
+
const shares = typeof options.shares === "string" ? BigInt(options.shares) : options.shares;
|
|
1402
|
+
const data = encodeFunctionData2({
|
|
1403
|
+
abi: STAKING_ABI,
|
|
1404
|
+
functionName: "validatorExit",
|
|
1405
|
+
args: [shares]
|
|
1406
|
+
});
|
|
1407
|
+
return executeWrite({ to: getStakingAddress(), data });
|
|
1408
|
+
},
|
|
1409
|
+
validatorClaim: async (options) => {
|
|
1410
|
+
if (!options?.validator && !client.account) {
|
|
1411
|
+
throw new Error("Either provide validator address or initialize client with an account");
|
|
1412
|
+
}
|
|
1413
|
+
const validatorAddress = options?.validator || client.account.address;
|
|
1414
|
+
const data = encodeFunctionData2({
|
|
1415
|
+
abi: STAKING_ABI,
|
|
1416
|
+
functionName: "validatorClaim",
|
|
1417
|
+
args: [validatorAddress]
|
|
1418
|
+
});
|
|
1419
|
+
const result = await executeWrite({ to: getStakingAddress(), data });
|
|
1420
|
+
return { ...result, claimedAmount: 0n };
|
|
1421
|
+
},
|
|
1422
|
+
validatorPrime: async (options) => {
|
|
1423
|
+
const data = encodeFunctionData2({
|
|
1424
|
+
abi: STAKING_ABI,
|
|
1425
|
+
functionName: "validatorPrime",
|
|
1426
|
+
args: [options.validator]
|
|
1427
|
+
});
|
|
1428
|
+
return executeWrite({ to: getStakingAddress(), data });
|
|
1429
|
+
},
|
|
1430
|
+
setOperator: async (options) => {
|
|
1431
|
+
const data = encodeFunctionData2({
|
|
1432
|
+
abi: VALIDATOR_WALLET_ABI,
|
|
1433
|
+
functionName: "setOperator",
|
|
1434
|
+
args: [options.operator]
|
|
1435
|
+
});
|
|
1436
|
+
return executeWrite({ to: options.validator, data });
|
|
1437
|
+
},
|
|
1438
|
+
setIdentity: async (options) => {
|
|
1439
|
+
let extraCidBytes = "0x";
|
|
1440
|
+
if (options.extraCid) {
|
|
1441
|
+
if (options.extraCid.startsWith("0x")) {
|
|
1442
|
+
extraCidBytes = options.extraCid;
|
|
1443
|
+
} else {
|
|
1444
|
+
extraCidBytes = toHex4(new TextEncoder().encode(options.extraCid));
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
const data = encodeFunctionData2({
|
|
1448
|
+
abi: VALIDATOR_WALLET_ABI,
|
|
1449
|
+
functionName: "setIdentity",
|
|
1450
|
+
args: [
|
|
1451
|
+
options.moniker,
|
|
1452
|
+
options.logoUri || "",
|
|
1453
|
+
options.website || "",
|
|
1454
|
+
options.description || "",
|
|
1455
|
+
options.email || "",
|
|
1456
|
+
options.twitter || "",
|
|
1457
|
+
options.telegram || "",
|
|
1458
|
+
options.github || "",
|
|
1459
|
+
extraCidBytes
|
|
1460
|
+
]
|
|
1461
|
+
});
|
|
1462
|
+
return executeWrite({ to: options.validator, data });
|
|
1463
|
+
},
|
|
1464
|
+
delegatorJoin: async (options) => {
|
|
1465
|
+
const amount = parseStakingAmount(options.amount);
|
|
1466
|
+
const data = encodeFunctionData2({
|
|
1467
|
+
abi: STAKING_ABI,
|
|
1468
|
+
functionName: "delegatorJoin",
|
|
1469
|
+
args: [options.validator]
|
|
1470
|
+
});
|
|
1471
|
+
const result = await executeWrite({ to: getStakingAddress(), data, value: amount });
|
|
1472
|
+
return {
|
|
1473
|
+
...result,
|
|
1474
|
+
validator: options.validator,
|
|
1475
|
+
delegator: client.account.address,
|
|
1476
|
+
amount: formatStakingAmount(amount),
|
|
1477
|
+
amountRaw: amount
|
|
1478
|
+
};
|
|
1479
|
+
},
|
|
1480
|
+
delegatorExit: async (options) => {
|
|
1481
|
+
const shares = typeof options.shares === "string" ? BigInt(options.shares) : options.shares;
|
|
1482
|
+
const data = encodeFunctionData2({
|
|
1483
|
+
abi: STAKING_ABI,
|
|
1484
|
+
functionName: "delegatorExit",
|
|
1485
|
+
args: [options.validator, shares]
|
|
1486
|
+
});
|
|
1487
|
+
return executeWrite({ to: getStakingAddress(), data });
|
|
1488
|
+
},
|
|
1489
|
+
delegatorClaim: async (options) => {
|
|
1490
|
+
if (!options.delegator && !client.account) {
|
|
1491
|
+
throw new Error("Either provide delegator address or initialize client with an account");
|
|
1492
|
+
}
|
|
1493
|
+
const delegatorAddress = options.delegator || client.account.address;
|
|
1494
|
+
const data = encodeFunctionData2({
|
|
1495
|
+
abi: STAKING_ABI,
|
|
1496
|
+
functionName: "delegatorClaim",
|
|
1497
|
+
args: [delegatorAddress, options.validator]
|
|
1498
|
+
});
|
|
1499
|
+
return executeWrite({ to: getStakingAddress(), data });
|
|
1500
|
+
},
|
|
1501
|
+
isValidator: async (address) => {
|
|
1502
|
+
const contract = getReadOnlyStakingContract();
|
|
1503
|
+
return contract.read.isValidator([address]);
|
|
1504
|
+
},
|
|
1505
|
+
getValidatorInfo: async (validator) => {
|
|
1506
|
+
const contract = getReadOnlyStakingContract();
|
|
1507
|
+
const isVal = await contract.read.isValidator([validator]);
|
|
1508
|
+
if (!isVal) {
|
|
1509
|
+
throw new Error(`Address ${validator} is not a validator`);
|
|
1510
|
+
}
|
|
1511
|
+
const walletContract = getContract({
|
|
1512
|
+
address: validator,
|
|
1513
|
+
abi: VALIDATOR_WALLET_ABI,
|
|
1514
|
+
client: publicClient
|
|
1515
|
+
});
|
|
1516
|
+
const [view, owner, operator, identityRaw, currentEpoch] = await Promise.all([
|
|
1517
|
+
contract.read.validatorView([validator]),
|
|
1518
|
+
walletContract.read.owner(),
|
|
1519
|
+
walletContract.read.operator(),
|
|
1520
|
+
walletContract.read.getIdentity().catch(() => null),
|
|
1521
|
+
contract.read.epoch()
|
|
1522
|
+
]);
|
|
1523
|
+
let identity;
|
|
1524
|
+
if (identityRaw && identityRaw.moniker) {
|
|
1525
|
+
identity = {
|
|
1526
|
+
moniker: identityRaw.moniker,
|
|
1527
|
+
logoUri: identityRaw.logoUri,
|
|
1528
|
+
website: identityRaw.website,
|
|
1529
|
+
description: identityRaw.description,
|
|
1530
|
+
email: identityRaw.email,
|
|
1531
|
+
twitter: identityRaw.twitter,
|
|
1532
|
+
telegram: identityRaw.telegram,
|
|
1533
|
+
github: identityRaw.github,
|
|
1534
|
+
extraCid: identityRaw.extraCid ? toHex4(identityRaw.extraCid) : ""
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1537
|
+
const needsPriming = currentEpoch > 0n && view.ePrimed < currentEpoch - 1n;
|
|
1538
|
+
const depositLen = await contract.read.validatorDepositLen([validator]);
|
|
1539
|
+
const pendingDeposits = [];
|
|
1540
|
+
for (let i = 0n; i < depositLen; i++) {
|
|
1541
|
+
const [epoch, commit] = await contract.read.validatorDeposit([validator, i]);
|
|
1542
|
+
pendingDeposits.push({
|
|
1543
|
+
epoch,
|
|
1544
|
+
stake: formatStakingAmount(commit.input),
|
|
1545
|
+
stakeRaw: commit.input,
|
|
1546
|
+
shares: commit.output
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
const withdrawalLen = await contract.read.validatorWithdrawalLen([validator]);
|
|
1550
|
+
const pendingWithdrawals = [];
|
|
1551
|
+
for (let i = 0n; i < withdrawalLen; i++) {
|
|
1552
|
+
const [epoch, commit] = await contract.read.validatorWithdrawal([validator, i]);
|
|
1553
|
+
pendingWithdrawals.push({
|
|
1554
|
+
epoch,
|
|
1555
|
+
shares: commit.input,
|
|
1556
|
+
stake: formatStakingAmount(commit.output),
|
|
1557
|
+
stakeRaw: commit.output
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
return {
|
|
1561
|
+
address: validator,
|
|
1562
|
+
owner,
|
|
1563
|
+
operator,
|
|
1564
|
+
vStake: formatStakingAmount(view.vStake),
|
|
1565
|
+
vStakeRaw: view.vStake,
|
|
1566
|
+
vShares: view.vShares,
|
|
1567
|
+
dStake: formatStakingAmount(view.dStake),
|
|
1568
|
+
dStakeRaw: view.dStake,
|
|
1569
|
+
dShares: view.dShares,
|
|
1570
|
+
vDeposit: formatStakingAmount(view.vDeposit),
|
|
1571
|
+
vDepositRaw: view.vDeposit,
|
|
1572
|
+
vWithdrawal: formatStakingAmount(view.vWithdrawal),
|
|
1573
|
+
vWithdrawalRaw: view.vWithdrawal,
|
|
1574
|
+
ePrimed: view.ePrimed,
|
|
1575
|
+
live: view.live,
|
|
1576
|
+
banned: view.eBanned > 0n,
|
|
1577
|
+
bannedEpoch: view.eBanned > 0n ? view.eBanned : void 0,
|
|
1578
|
+
needsPriming,
|
|
1579
|
+
identity,
|
|
1580
|
+
pendingDeposits,
|
|
1581
|
+
pendingWithdrawals
|
|
1582
|
+
};
|
|
1583
|
+
},
|
|
1584
|
+
getStakeInfo: async (delegator, validator) => {
|
|
1585
|
+
const contract = getReadOnlyStakingContract();
|
|
1586
|
+
const shares = await contract.read.sharesOf([delegator, validator]);
|
|
1587
|
+
let stake = 0n;
|
|
1588
|
+
if (shares > 0n) {
|
|
1589
|
+
stake = await contract.read.stakeOf([delegator, validator]);
|
|
1590
|
+
}
|
|
1591
|
+
const depositLen = await contract.read.delegatorDepositLen([
|
|
1592
|
+
delegator,
|
|
1593
|
+
validator
|
|
1594
|
+
]);
|
|
1595
|
+
const pendingDeposits = [];
|
|
1596
|
+
for (let i = 0n; i < depositLen; i++) {
|
|
1597
|
+
const [claim, commit] = await contract.read.delegatorDeposit([
|
|
1598
|
+
delegator,
|
|
1599
|
+
validator,
|
|
1600
|
+
i
|
|
1601
|
+
]);
|
|
1602
|
+
pendingDeposits.push({
|
|
1603
|
+
epoch: commit.epoch,
|
|
1604
|
+
stake: formatStakingAmount(commit.input),
|
|
1605
|
+
stakeRaw: commit.input,
|
|
1606
|
+
shares: claim.quantity
|
|
1607
|
+
});
|
|
1608
|
+
}
|
|
1609
|
+
const withdrawalLen = await contract.read.delegatorWithdrawalLen([
|
|
1610
|
+
delegator,
|
|
1611
|
+
validator
|
|
1612
|
+
]);
|
|
1613
|
+
const pendingWithdrawals = [];
|
|
1614
|
+
for (let i = 0n; i < withdrawalLen; i++) {
|
|
1615
|
+
const [claim, commit] = await contract.read.delegatorWithdrawal([
|
|
1616
|
+
delegator,
|
|
1617
|
+
validator,
|
|
1618
|
+
i
|
|
1619
|
+
]);
|
|
1620
|
+
pendingWithdrawals.push({
|
|
1621
|
+
epoch: commit.epoch,
|
|
1622
|
+
shares: claim.quantity,
|
|
1623
|
+
stake: formatStakingAmount(commit.output),
|
|
1624
|
+
stakeRaw: commit.output
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1627
|
+
return {
|
|
1628
|
+
delegator,
|
|
1629
|
+
validator,
|
|
1630
|
+
shares,
|
|
1631
|
+
stake: formatStakingAmount(stake),
|
|
1632
|
+
stakeRaw: stake,
|
|
1633
|
+
pendingDeposits,
|
|
1634
|
+
pendingWithdrawals
|
|
1635
|
+
};
|
|
1636
|
+
},
|
|
1637
|
+
getEpochInfo: async () => {
|
|
1638
|
+
const contract = getReadOnlyStakingContract();
|
|
1639
|
+
const [
|
|
1640
|
+
epoch,
|
|
1641
|
+
validatorMinStake,
|
|
1642
|
+
delegatorMinStake,
|
|
1643
|
+
activeCount,
|
|
1644
|
+
epochMinDuration,
|
|
1645
|
+
epochZeroMinDuration,
|
|
1646
|
+
epochOdd,
|
|
1647
|
+
epochEven
|
|
1648
|
+
] = await Promise.all([
|
|
1649
|
+
contract.read.epoch(),
|
|
1650
|
+
contract.read.validatorMinStake(),
|
|
1651
|
+
contract.read.delegatorMinStake(),
|
|
1652
|
+
contract.read.activeValidatorsCount(),
|
|
1653
|
+
contract.read.epochMinDuration(),
|
|
1654
|
+
contract.read.epochZeroMinDuration(),
|
|
1655
|
+
contract.read.epochOdd(),
|
|
1656
|
+
contract.read.epochEven()
|
|
1657
|
+
]);
|
|
1658
|
+
const currentEpochData = epoch % 2n === 0n ? epochEven : epochOdd;
|
|
1659
|
+
const currentEpochStart = new Date(Number(currentEpochData.start) * 1e3);
|
|
1660
|
+
const currentEpochEnd = currentEpochData.end > 0n ? new Date(Number(currentEpochData.end) * 1e3) : null;
|
|
1661
|
+
let nextEpochEstimate = null;
|
|
1662
|
+
if (!currentEpochEnd) {
|
|
1663
|
+
const duration = epoch === 0n ? epochZeroMinDuration : epochMinDuration;
|
|
1664
|
+
const estimatedEndMs = Number(currentEpochData.start + duration) * 1e3;
|
|
1665
|
+
nextEpochEstimate = new Date(estimatedEndMs);
|
|
1666
|
+
}
|
|
1667
|
+
return {
|
|
1668
|
+
currentEpoch: epoch,
|
|
1669
|
+
validatorMinStake: formatStakingAmount(validatorMinStake),
|
|
1670
|
+
validatorMinStakeRaw: validatorMinStake,
|
|
1671
|
+
delegatorMinStake: formatStakingAmount(delegatorMinStake),
|
|
1672
|
+
delegatorMinStakeRaw: delegatorMinStake,
|
|
1673
|
+
activeValidatorsCount: activeCount,
|
|
1674
|
+
epochMinDuration,
|
|
1675
|
+
currentEpochStart,
|
|
1676
|
+
currentEpochEnd,
|
|
1677
|
+
nextEpochEstimate,
|
|
1678
|
+
inflation: formatStakingAmount(currentEpochData.inflation),
|
|
1679
|
+
inflationRaw: currentEpochData.inflation,
|
|
1680
|
+
totalWeight: currentEpochData.weight,
|
|
1681
|
+
totalClaimed: formatStakingAmount(currentEpochData.claimed),
|
|
1682
|
+
totalClaimedRaw: currentEpochData.claimed
|
|
1683
|
+
};
|
|
1684
|
+
},
|
|
1685
|
+
getActiveValidators: async () => {
|
|
1686
|
+
const contract = getReadOnlyStakingContract();
|
|
1687
|
+
const validators = await contract.read.activeValidators();
|
|
1688
|
+
return validators.filter((v) => v !== "0x0000000000000000000000000000000000000000");
|
|
1689
|
+
},
|
|
1690
|
+
getActiveValidatorsCount: async () => {
|
|
1691
|
+
const contract = getReadOnlyStakingContract();
|
|
1692
|
+
return contract.read.activeValidatorsCount();
|
|
1693
|
+
},
|
|
1694
|
+
getQuarantinedValidators: async () => {
|
|
1695
|
+
const contract = getReadOnlyStakingContract();
|
|
1696
|
+
return contract.read.getQuarantinedValidators();
|
|
1697
|
+
},
|
|
1698
|
+
getBannedValidators: async (startIndex = 0n, size = 100n) => {
|
|
1699
|
+
const contract = getReadOnlyStakingContract();
|
|
1700
|
+
const result = await contract.read.getAllBannedValidators([startIndex, size]);
|
|
1701
|
+
return result.map((v) => ({
|
|
1702
|
+
validator: v.validator,
|
|
1703
|
+
untilEpoch: v.untilEpochBanned,
|
|
1704
|
+
permanentlyBanned: v.permanentlyBanned
|
|
1705
|
+
}));
|
|
1706
|
+
},
|
|
1707
|
+
getQuarantinedValidatorsDetailed: async (startIndex = 0n, size = 100n) => {
|
|
1708
|
+
const contract = getReadOnlyStakingContract();
|
|
1709
|
+
const result = await contract.read.getAllQuarantinedValidators([startIndex, size]);
|
|
1710
|
+
return result.map((v) => ({
|
|
1711
|
+
validator: v.validator,
|
|
1712
|
+
untilEpoch: v.untilEpochBanned,
|
|
1713
|
+
permanentlyBanned: v.permanentlyBanned
|
|
1714
|
+
}));
|
|
1715
|
+
},
|
|
1716
|
+
getStakingContract,
|
|
1717
|
+
parseStakingAmount,
|
|
1718
|
+
formatStakingAmount
|
|
1719
|
+
};
|
|
1720
|
+
};
|
|
1721
|
+
|
|
1215
1722
|
// src/chains/actions.ts
|
|
1216
1723
|
function chainActions(client) {
|
|
1217
1724
|
return {
|
|
@@ -1249,17 +1756,17 @@ var getCustomTransportConfig = (config) => {
|
|
|
1249
1756
|
return {
|
|
1250
1757
|
async request({ method, params = [] }) {
|
|
1251
1758
|
if (method.startsWith("eth_") && isAddress) {
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1759
|
+
const provider = config.provider || (typeof window !== "undefined" ? window.ethereum : void 0);
|
|
1760
|
+
if (provider) {
|
|
1761
|
+
try {
|
|
1762
|
+
return await provider.request({ method, params });
|
|
1763
|
+
} catch (err) {
|
|
1764
|
+
console.warn(`Error using provider for method ${method}:`, err);
|
|
1765
|
+
throw err;
|
|
1256
1766
|
}
|
|
1257
|
-
return await provider.request({ method, params });
|
|
1258
|
-
} catch (err) {
|
|
1259
|
-
console.warn(`Error using provider for method ${method}:`, err);
|
|
1260
|
-
throw err;
|
|
1261
1767
|
}
|
|
1262
|
-
}
|
|
1768
|
+
}
|
|
1769
|
+
{
|
|
1263
1770
|
if (!config.chain) {
|
|
1264
1771
|
throw new Error("Chain is not set");
|
|
1265
1772
|
}
|
|
@@ -1314,10 +1821,14 @@ var createClient = (config = { chain: localnet }) => {
|
|
|
1314
1821
|
...clientWithTransactionActions,
|
|
1315
1822
|
...contractActions(clientWithTransactionActions, publicClient)
|
|
1316
1823
|
};
|
|
1317
|
-
const
|
|
1824
|
+
const clientWithReceiptActions = {
|
|
1318
1825
|
...clientWithAllActions,
|
|
1319
1826
|
...receiptActions(clientWithAllActions, publicClient)
|
|
1320
1827
|
};
|
|
1828
|
+
const finalClient = {
|
|
1829
|
+
...clientWithReceiptActions,
|
|
1830
|
+
...stakingActions(clientWithReceiptActions, publicClient)
|
|
1831
|
+
};
|
|
1321
1832
|
finalClient.initializeConsensusSmartContract().catch((error) => {
|
|
1322
1833
|
console.error("Failed to initialize consensus smart contract:", error);
|
|
1323
1834
|
});
|
|
@@ -1343,6 +1854,8 @@ export {
|
|
|
1343
1854
|
decodeInputData,
|
|
1344
1855
|
decodeLocalnetTransaction,
|
|
1345
1856
|
decodeTransaction,
|
|
1857
|
+
formatStakingAmount,
|
|
1346
1858
|
generatePrivateKey,
|
|
1859
|
+
parseStakingAmount,
|
|
1347
1860
|
simplifyTransactionReceipt
|
|
1348
1861
|
};
|