genlayer-js 0.18.7 → 0.18.9
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 +4 -0
- package/dist/chains/index.cjs +2 -2
- package/dist/chains/index.js +1 -1
- package/dist/{chunk-I23SLL2A.cjs → chunk-SC2VXHL3.cjs} +102 -2
- package/dist/{chunk-RW6PLN5W.js → chunk-V3MYVW3P.js} +102 -2
- package/dist/{index-DM646L5c.d.cts → index-D9ONjYgl.d.cts} +162 -22
- package/dist/{index-9QkkDjYm.d.ts → index-ZDqJWXj0.d.ts} +162 -22
- package/dist/index.cjs +133 -94
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +88 -49
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/abi/staking.ts +122 -0
- package/src/client/client.ts +3 -7
- package/src/contracts/actions.ts +60 -41
- package/src/staking/actions.ts +49 -11
- package/src/types/staking.ts +4 -7
- package/src/types/transactions.ts +16 -14
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
localnet,
|
|
6
6
|
studionet,
|
|
7
7
|
testnetAsimov
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-V3MYVW3P.js";
|
|
9
9
|
import {
|
|
10
10
|
CalldataAddress,
|
|
11
11
|
isDecidedState,
|
|
@@ -743,10 +743,44 @@ var _sendTransaction = async ({
|
|
|
743
743
|
data: encodedData,
|
|
744
744
|
value
|
|
745
745
|
});
|
|
746
|
-
} catch (
|
|
747
|
-
console.
|
|
746
|
+
} catch (err) {
|
|
747
|
+
console.error("Gas estimation failed, using default 200_000:", err);
|
|
748
748
|
estimatedGas = 200000n;
|
|
749
749
|
}
|
|
750
|
+
if (validatedSenderAccount?.type === "local") {
|
|
751
|
+
if (!validatedSenderAccount?.signTransaction) {
|
|
752
|
+
throw new Error("Account does not support signTransaction");
|
|
753
|
+
}
|
|
754
|
+
const gasPriceHex = await client.request({
|
|
755
|
+
method: "eth_gasPrice"
|
|
756
|
+
});
|
|
757
|
+
const transactionRequest2 = {
|
|
758
|
+
account: validatedSenderAccount,
|
|
759
|
+
to: client.chain.consensusMainContract?.address,
|
|
760
|
+
data: encodedData,
|
|
761
|
+
type: "legacy",
|
|
762
|
+
nonce: Number(nonce),
|
|
763
|
+
value,
|
|
764
|
+
gas: estimatedGas,
|
|
765
|
+
gasPrice: BigInt(gasPriceHex),
|
|
766
|
+
chainId: client.chain.id
|
|
767
|
+
};
|
|
768
|
+
const serializedTransaction = await validatedSenderAccount.signTransaction(transactionRequest2);
|
|
769
|
+
const txHash = await client.sendRawTransaction({ serializedTransaction });
|
|
770
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
771
|
+
if (receipt.status === "reverted") {
|
|
772
|
+
throw new Error("Transaction reverted");
|
|
773
|
+
}
|
|
774
|
+
const newTxEvents = parseEventLogs({
|
|
775
|
+
abi: client.chain.consensusMainContract?.abi,
|
|
776
|
+
eventName: "NewTransaction",
|
|
777
|
+
logs: receipt.logs
|
|
778
|
+
});
|
|
779
|
+
if (newTxEvents.length === 0) {
|
|
780
|
+
throw new Error("Transaction not processed by consensus");
|
|
781
|
+
}
|
|
782
|
+
return newTxEvents[0].args["txId"];
|
|
783
|
+
}
|
|
750
784
|
const transactionRequest = await client.prepareTransactionRequest({
|
|
751
785
|
account: validatedSenderAccount,
|
|
752
786
|
to: client.chain.consensusMainContract?.address,
|
|
@@ -756,37 +790,17 @@ var _sendTransaction = async ({
|
|
|
756
790
|
value,
|
|
757
791
|
gas: estimatedGas
|
|
758
792
|
});
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
params: [formattedRequest]
|
|
770
|
-
});
|
|
771
|
-
}
|
|
772
|
-
if (!validatedSenderAccount?.signTransaction) {
|
|
773
|
-
throw new Error("Account does not support signTransaction");
|
|
774
|
-
}
|
|
775
|
-
const serializedTransaction = await validatedSenderAccount.signTransaction(transactionRequest);
|
|
776
|
-
const txHash = await client.sendRawTransaction({ serializedTransaction });
|
|
777
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
778
|
-
if (receipt.status === "reverted") {
|
|
779
|
-
throw new Error("Transaction reverted");
|
|
780
|
-
}
|
|
781
|
-
const newTxEvents = parseEventLogs({
|
|
782
|
-
abi: client.chain.consensusMainContract?.abi,
|
|
783
|
-
eventName: "NewTransaction",
|
|
784
|
-
logs: receipt.logs
|
|
793
|
+
const formattedRequest = {
|
|
794
|
+
from: transactionRequest.from,
|
|
795
|
+
to: transactionRequest.to,
|
|
796
|
+
data: encodedData,
|
|
797
|
+
value: transactionRequest.value ? `0x${transactionRequest.value.toString(16)}` : "0x0",
|
|
798
|
+
gas: transactionRequest.gas ? `0x${transactionRequest.gas.toString(16)}` : "0x5208"
|
|
799
|
+
};
|
|
800
|
+
return await client.request({
|
|
801
|
+
method: "eth_sendTransaction",
|
|
802
|
+
params: [formattedRequest]
|
|
785
803
|
});
|
|
786
|
-
if (newTxEvents.length === 0) {
|
|
787
|
-
throw new Error("Transaction not processed by consensus");
|
|
788
|
-
}
|
|
789
|
-
return newTxEvents[0].args["txId"];
|
|
790
804
|
};
|
|
791
805
|
|
|
792
806
|
// src/config/transactions.ts
|
|
@@ -1672,6 +1686,7 @@ var stakingActions = (client, publicClient) => {
|
|
|
1672
1686
|
const contract = getReadOnlyStakingContract();
|
|
1673
1687
|
const [
|
|
1674
1688
|
epoch,
|
|
1689
|
+
finalized,
|
|
1675
1690
|
validatorMinStake,
|
|
1676
1691
|
delegatorMinStake,
|
|
1677
1692
|
activeCount,
|
|
@@ -1681,6 +1696,7 @@ var stakingActions = (client, publicClient) => {
|
|
|
1681
1696
|
epochEven
|
|
1682
1697
|
] = await Promise.all([
|
|
1683
1698
|
contract.read.epoch(),
|
|
1699
|
+
contract.read.finalized(),
|
|
1684
1700
|
contract.read.validatorMinStake(),
|
|
1685
1701
|
contract.read.delegatorMinStake(),
|
|
1686
1702
|
contract.read.activeValidatorsCount(),
|
|
@@ -1690,8 +1706,7 @@ var stakingActions = (client, publicClient) => {
|
|
|
1690
1706
|
contract.read.epochEven()
|
|
1691
1707
|
]);
|
|
1692
1708
|
const currentEpochData = epoch % 2n === 0n ? epochEven : epochOdd;
|
|
1693
|
-
const
|
|
1694
|
-
const currentEpochEnd = currentEpochData.end > 0n ? new Date(Number(currentEpochData.end) * 1e3) : null;
|
|
1709
|
+
const currentEpochEnd = currentEpochData.end > 0n;
|
|
1695
1710
|
let nextEpochEstimate = null;
|
|
1696
1711
|
if (!currentEpochEnd) {
|
|
1697
1712
|
const duration = epoch === 0n ? epochZeroMinDuration : epochMinDuration;
|
|
@@ -1700,20 +1715,42 @@ var stakingActions = (client, publicClient) => {
|
|
|
1700
1715
|
}
|
|
1701
1716
|
return {
|
|
1702
1717
|
currentEpoch: epoch,
|
|
1718
|
+
lastFinalizedEpoch: finalized,
|
|
1703
1719
|
validatorMinStake: formatStakingAmount(validatorMinStake),
|
|
1704
1720
|
validatorMinStakeRaw: validatorMinStake,
|
|
1705
1721
|
delegatorMinStake: formatStakingAmount(delegatorMinStake),
|
|
1706
1722
|
delegatorMinStakeRaw: delegatorMinStake,
|
|
1707
1723
|
activeValidatorsCount: activeCount,
|
|
1708
1724
|
epochMinDuration,
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1725
|
+
nextEpochEstimate
|
|
1726
|
+
};
|
|
1727
|
+
},
|
|
1728
|
+
getEpochData: async (epochNumber) => {
|
|
1729
|
+
const contract = getReadOnlyStakingContract();
|
|
1730
|
+
const [currentEpoch, epochOdd, epochEven] = await Promise.all([
|
|
1731
|
+
contract.read.epoch(),
|
|
1732
|
+
contract.read.epochOdd(),
|
|
1733
|
+
contract.read.epochEven()
|
|
1734
|
+
]);
|
|
1735
|
+
if (epochNumber > currentEpoch) {
|
|
1736
|
+
throw new Error(`Epoch ${epochNumber} has not started yet (current: ${currentEpoch})`);
|
|
1737
|
+
}
|
|
1738
|
+
if (epochNumber < currentEpoch - 1n && currentEpoch > 0n) {
|
|
1739
|
+
throw new Error(`Epoch ${epochNumber} data no longer available (only current and previous epoch stored)`);
|
|
1740
|
+
}
|
|
1741
|
+
const epochData = epochNumber % 2n === 0n ? epochEven : epochOdd;
|
|
1742
|
+
return {
|
|
1743
|
+
start: epochData.start,
|
|
1744
|
+
end: epochData.end,
|
|
1745
|
+
inflation: epochData.inflation,
|
|
1746
|
+
weight: epochData.weight,
|
|
1747
|
+
weightDeposit: epochData.weightDeposit,
|
|
1748
|
+
weightWithdrawal: epochData.weightWithdrawal,
|
|
1749
|
+
vcount: epochData.vcount,
|
|
1750
|
+
claimed: epochData.claimed,
|
|
1751
|
+
stakeDeposit: epochData.stakeDeposit,
|
|
1752
|
+
stakeWithdrawal: epochData.stakeWithdrawal,
|
|
1753
|
+
slashed: epochData.slashed
|
|
1717
1754
|
};
|
|
1718
1755
|
},
|
|
1719
1756
|
getActiveValidators: async () => {
|
|
@@ -1747,6 +1784,11 @@ var stakingActions = (client, publicClient) => {
|
|
|
1747
1784
|
permanentlyBanned: v.permanentlyBanned
|
|
1748
1785
|
}));
|
|
1749
1786
|
},
|
|
1787
|
+
getSlashingAddress: async () => {
|
|
1788
|
+
const contract = getReadOnlyStakingContract();
|
|
1789
|
+
const externalContracts = await contract.read.contracts();
|
|
1790
|
+
return externalContracts[4];
|
|
1791
|
+
},
|
|
1750
1792
|
getStakingContract,
|
|
1751
1793
|
parseStakingAmount,
|
|
1752
1794
|
formatStakingAmount
|
|
@@ -1785,7 +1827,7 @@ function chainActions(client) {
|
|
|
1785
1827
|
}
|
|
1786
1828
|
|
|
1787
1829
|
// src/client/client.ts
|
|
1788
|
-
var getCustomTransportConfig = (config) => {
|
|
1830
|
+
var getCustomTransportConfig = (config, chainConfig) => {
|
|
1789
1831
|
const isAddress = typeof config.account !== "object";
|
|
1790
1832
|
return {
|
|
1791
1833
|
async request({ method, params = [] }) {
|
|
@@ -1801,11 +1843,8 @@ var getCustomTransportConfig = (config) => {
|
|
|
1801
1843
|
}
|
|
1802
1844
|
}
|
|
1803
1845
|
{
|
|
1804
|
-
if (!config.chain) {
|
|
1805
|
-
throw new Error("Chain is not set");
|
|
1806
|
-
}
|
|
1807
1846
|
try {
|
|
1808
|
-
const response = await fetch(
|
|
1847
|
+
const response = await fetch(chainConfig.rpcUrls.default.http[0], {
|
|
1809
1848
|
method: "POST",
|
|
1810
1849
|
headers: {
|
|
1811
1850
|
"Content-Type": "application/json"
|
|
@@ -1835,7 +1874,7 @@ var createClient = (config = { chain: localnet }) => {
|
|
|
1835
1874
|
if (config.endpoint) {
|
|
1836
1875
|
chainConfig.rpcUrls.default.http = [config.endpoint];
|
|
1837
1876
|
}
|
|
1838
|
-
const customTransport = custom(getCustomTransportConfig(config), { retryCount: 0, retryDelay: 0 });
|
|
1877
|
+
const customTransport = custom(getCustomTransportConfig(config, chainConfig), { retryCount: 0, retryDelay: 0 });
|
|
1839
1878
|
const publicClient = createPublicClient(chainConfig, customTransport).extend(
|
|
1840
1879
|
publicActions
|
|
1841
1880
|
);
|
package/dist/types/index.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Account, Address } from 'viem';
|
|
2
|
-
export { I as BannedValidatorInfo, d as CalldataAddress, C as CalldataEncodable, i as ContractMethod, h as ContractMethodBase, f as ContractParamsArraySchemaElement, g as ContractParamsSchema, j as ContractSchema, o as DECIDED_STATES, a as DecodedCallData, D as DecodedDeployData,
|
|
2
|
+
export { I as BannedValidatorInfo, d as CalldataAddress, C as CalldataEncodable, i as ContractMethod, h as ContractMethodBase, f as ContractParamsArraySchemaElement, g as ContractParamsSchema, j as ContractSchema, o as DECIDED_STATES, a as DecodedCallData, D as DecodedDeployData, a4 as DelegatorClaimOptions, a3 as DelegatorExitOptions, a2 as DelegatorJoinOptions, U as DelegatorJoinResult, K as EpochData, O as EpochInfo, G as GenLayerClient, e as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, L as LeaderReceipt, M as MethodDescription, N as Network, P as PendingDeposit, F as PendingWithdrawal, a1 as SetIdentityOptions, a0 as SetOperatorOptions, y as SnapSource, J as StakeInfo, a5 as StakingActions, z as StakingContract, Q as StakingTransactionResult, k as TransactionHash, x as TransactionHashVariant, m as TransactionResult, r as TransactionResultNameToNumber, l as TransactionStatus, w as TransactionType, _ as ValidatorClaimOptions, Y as ValidatorDepositOptions, Z as ValidatorExitOptions, B as ValidatorIdentity, E as ValidatorInfo, X as ValidatorJoinOptions, R as ValidatorJoinResult, $ as ValidatorPrimeOptions, A as ValidatorView, s as VoteType, W as WithdrawalCommit, p as isDecidedState, q as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, u as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-D9ONjYgl.cjs';
|
|
3
3
|
export { G as GenLayerChain } from '../chains-B7B7UXdn.cjs';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Account, Address } from 'viem';
|
|
2
|
-
export { I as BannedValidatorInfo, d as CalldataAddress, C as CalldataEncodable, i as ContractMethod, h as ContractMethodBase, f as ContractParamsArraySchemaElement, g as ContractParamsSchema, j as ContractSchema, o as DECIDED_STATES, a as DecodedCallData, D as DecodedDeployData,
|
|
2
|
+
export { I as BannedValidatorInfo, d as CalldataAddress, C as CalldataEncodable, i as ContractMethod, h as ContractMethodBase, f as ContractParamsArraySchemaElement, g as ContractParamsSchema, j as ContractSchema, o as DECIDED_STATES, a as DecodedCallData, D as DecodedDeployData, a4 as DelegatorClaimOptions, a3 as DelegatorExitOptions, a2 as DelegatorJoinOptions, U as DelegatorJoinResult, K as EpochData, O as EpochInfo, G as GenLayerClient, e as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, L as LeaderReceipt, M as MethodDescription, N as Network, P as PendingDeposit, F as PendingWithdrawal, a1 as SetIdentityOptions, a0 as SetOperatorOptions, y as SnapSource, J as StakeInfo, a5 as StakingActions, z as StakingContract, Q as StakingTransactionResult, k as TransactionHash, x as TransactionHashVariant, m as TransactionResult, r as TransactionResultNameToNumber, l as TransactionStatus, w as TransactionType, _ as ValidatorClaimOptions, Y as ValidatorDepositOptions, Z as ValidatorExitOptions, B as ValidatorIdentity, E as ValidatorInfo, X as ValidatorJoinOptions, R as ValidatorJoinResult, $ as ValidatorPrimeOptions, A as ValidatorView, s as VoteType, W as WithdrawalCommit, p as isDecidedState, q as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, u as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-ZDqJWXj0.js';
|
|
3
3
|
export { G as GenLayerChain } from '../chains-B7B7UXdn.js';
|
package/package.json
CHANGED
package/src/abi/staking.ts
CHANGED
|
@@ -6,6 +6,9 @@ export const VALIDATOR_WALLET_ABI = [
|
|
|
6
6
|
{name: "TransferFailed", type: "error", inputs: []},
|
|
7
7
|
{name: "OperatorTransferNotReady", type: "error", inputs: []},
|
|
8
8
|
{name: "NoPendingOperator", type: "error", inputs: []},
|
|
9
|
+
// OpenZeppelin Ownable errors
|
|
10
|
+
{name: "OwnableUnauthorizedAccount", type: "error", inputs: [{name: "account", type: "address"}]},
|
|
11
|
+
{name: "OwnableInvalidOwner", type: "error", inputs: [{name: "owner", type: "address"}]},
|
|
9
12
|
|
|
10
13
|
// Functions
|
|
11
14
|
{
|
|
@@ -69,6 +72,67 @@ export const VALIDATOR_WALLET_ABI = [
|
|
|
69
72
|
],
|
|
70
73
|
outputs: [],
|
|
71
74
|
},
|
|
75
|
+
// Staking functions (forwarded to staking contract)
|
|
76
|
+
{
|
|
77
|
+
name: "validatorDeposit",
|
|
78
|
+
type: "function",
|
|
79
|
+
stateMutability: "payable",
|
|
80
|
+
inputs: [],
|
|
81
|
+
outputs: [],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "validatorExit",
|
|
85
|
+
type: "function",
|
|
86
|
+
stateMutability: "nonpayable",
|
|
87
|
+
inputs: [{name: "_shares", type: "uint256"}],
|
|
88
|
+
outputs: [],
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "validatorClaim",
|
|
92
|
+
type: "function",
|
|
93
|
+
stateMutability: "nonpayable",
|
|
94
|
+
inputs: [],
|
|
95
|
+
outputs: [],
|
|
96
|
+
},
|
|
97
|
+
// Two-step operator transfer
|
|
98
|
+
{
|
|
99
|
+
name: "initiateOperatorTransfer",
|
|
100
|
+
type: "function",
|
|
101
|
+
stateMutability: "nonpayable",
|
|
102
|
+
inputs: [{name: "_newOperator", type: "address"}],
|
|
103
|
+
outputs: [],
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: "completeOperatorTransfer",
|
|
107
|
+
type: "function",
|
|
108
|
+
stateMutability: "nonpayable",
|
|
109
|
+
inputs: [],
|
|
110
|
+
outputs: [],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "cancelOperatorTransfer",
|
|
114
|
+
type: "function",
|
|
115
|
+
stateMutability: "nonpayable",
|
|
116
|
+
inputs: [],
|
|
117
|
+
outputs: [],
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "getPendingOperator",
|
|
121
|
+
type: "function",
|
|
122
|
+
stateMutability: "view",
|
|
123
|
+
inputs: [],
|
|
124
|
+
outputs: [
|
|
125
|
+
{name: "", type: "address"},
|
|
126
|
+
{name: "", type: "uint256"},
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: "getOperator",
|
|
131
|
+
type: "function",
|
|
132
|
+
stateMutability: "view",
|
|
133
|
+
inputs: [],
|
|
134
|
+
outputs: [{name: "", type: "address"}],
|
|
135
|
+
},
|
|
72
136
|
] as const;
|
|
73
137
|
|
|
74
138
|
export const STAKING_ABI = [
|
|
@@ -250,6 +314,13 @@ export const STAKING_ABI = [
|
|
|
250
314
|
inputs: [],
|
|
251
315
|
outputs: [{name: "", type: "uint256"}],
|
|
252
316
|
},
|
|
317
|
+
{
|
|
318
|
+
name: "finalized",
|
|
319
|
+
type: "function",
|
|
320
|
+
stateMutability: "view",
|
|
321
|
+
inputs: [],
|
|
322
|
+
outputs: [{name: "", type: "uint256"}],
|
|
323
|
+
},
|
|
253
324
|
{
|
|
254
325
|
name: "validatorMinStake",
|
|
255
326
|
type: "function",
|
|
@@ -298,6 +369,7 @@ export const STAKING_ABI = [
|
|
|
298
369
|
{name: "claimed", type: "uint256"},
|
|
299
370
|
{name: "stakeDeposit", type: "uint256"},
|
|
300
371
|
{name: "stakeWithdrawal", type: "uint256"},
|
|
372
|
+
{name: "slashed", type: "uint256"},
|
|
301
373
|
],
|
|
302
374
|
},
|
|
303
375
|
],
|
|
@@ -322,6 +394,7 @@ export const STAKING_ABI = [
|
|
|
322
394
|
{name: "claimed", type: "uint256"},
|
|
323
395
|
{name: "stakeDeposit", type: "uint256"},
|
|
324
396
|
{name: "stakeWithdrawal", type: "uint256"},
|
|
397
|
+
{name: "slashed", type: "uint256"},
|
|
325
398
|
],
|
|
326
399
|
},
|
|
327
400
|
],
|
|
@@ -562,4 +635,53 @@ export const STAKING_ABI = [
|
|
|
562
635
|
{name: "amount", type: "uint256", indexed: false},
|
|
563
636
|
],
|
|
564
637
|
},
|
|
638
|
+
{
|
|
639
|
+
name: "ValidatorPrime",
|
|
640
|
+
type: "event",
|
|
641
|
+
inputs: [
|
|
642
|
+
{name: "validator", type: "address", indexed: false},
|
|
643
|
+
{name: "epoch", type: "uint256", indexed: false},
|
|
644
|
+
{name: "validatorRewards", type: "uint256", indexed: false},
|
|
645
|
+
{name: "delegatorRewards", type: "uint256", indexed: false},
|
|
646
|
+
],
|
|
647
|
+
},
|
|
648
|
+
// External contracts getter
|
|
649
|
+
{
|
|
650
|
+
name: "contracts",
|
|
651
|
+
type: "function",
|
|
652
|
+
stateMutability: "view",
|
|
653
|
+
inputs: [],
|
|
654
|
+
outputs: [
|
|
655
|
+
{name: "gen", type: "address"},
|
|
656
|
+
{name: "transactions", type: "address"},
|
|
657
|
+
{name: "idleness", type: "address"},
|
|
658
|
+
{name: "tribunal", type: "address"},
|
|
659
|
+
{name: "slashing", type: "address"},
|
|
660
|
+
{name: "consensus", type: "address"},
|
|
661
|
+
{name: "validatorWalletFactory", type: "address"},
|
|
662
|
+
{name: "nftMinter", type: "address"},
|
|
663
|
+
],
|
|
664
|
+
},
|
|
665
|
+
] as const;
|
|
666
|
+
|
|
667
|
+
// Slash contract ABI for slashing events
|
|
668
|
+
export const SLASH_ABI = [
|
|
669
|
+
{
|
|
670
|
+
name: "SlashedFromIdleness",
|
|
671
|
+
type: "event",
|
|
672
|
+
inputs: [
|
|
673
|
+
{name: "validator", type: "address", indexed: true},
|
|
674
|
+
{name: "txId", type: "bytes32", indexed: false},
|
|
675
|
+
{name: "epoch", type: "uint256", indexed: false},
|
|
676
|
+
{name: "percentage", type: "uint256", indexed: false},
|
|
677
|
+
],
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
name: "SlashEnacted",
|
|
681
|
+
type: "event",
|
|
682
|
+
inputs: [
|
|
683
|
+
{name: "validator", type: "address", indexed: true},
|
|
684
|
+
{name: "epoch", type: "uint256", indexed: false},
|
|
685
|
+
],
|
|
686
|
+
},
|
|
565
687
|
] as const;
|
package/src/client/client.ts
CHANGED
|
@@ -33,7 +33,7 @@ interface ClientConfig {
|
|
|
33
33
|
provider?: EthereumProvider; // Custom provider for wallet framework integration
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const getCustomTransportConfig = (config: ClientConfig) => {
|
|
36
|
+
const getCustomTransportConfig = (config: ClientConfig, chainConfig: GenLayerChain) => {
|
|
37
37
|
const isAddress = typeof config.account !== "object";
|
|
38
38
|
|
|
39
39
|
return {
|
|
@@ -51,12 +51,8 @@ const getCustomTransportConfig = (config: ClientConfig) => {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
{
|
|
54
|
-
if (!config.chain) {
|
|
55
|
-
throw new Error("Chain is not set");
|
|
56
|
-
}
|
|
57
|
-
|
|
58
54
|
try {
|
|
59
|
-
const response = await fetch(
|
|
55
|
+
const response = await fetch(chainConfig.rpcUrls.default.http[0], {
|
|
60
56
|
method: "POST",
|
|
61
57
|
headers: {
|
|
62
58
|
"Content-Type": "application/json",
|
|
@@ -91,7 +87,7 @@ export const createClient = (config: ClientConfig = {chain: localnet}): GenLayer
|
|
|
91
87
|
chainConfig.rpcUrls.default.http = [config.endpoint];
|
|
92
88
|
}
|
|
93
89
|
|
|
94
|
-
const customTransport = custom(getCustomTransportConfig(config), {retryCount: 0, retryDelay: 0});
|
|
90
|
+
const customTransport = custom(getCustomTransportConfig(config, chainConfig as GenLayerChain), {retryCount: 0, retryDelay: 0});
|
|
95
91
|
const publicClient = createPublicClient(chainConfig as GenLayerChain, customTransport).extend(
|
|
96
92
|
publicActions,
|
|
97
93
|
);
|
package/src/contracts/actions.ts
CHANGED
|
@@ -301,8 +301,8 @@ const _sendTransaction = async ({
|
|
|
301
301
|
}
|
|
302
302
|
|
|
303
303
|
const validatedSenderAccount = validateAccount(senderAccount);
|
|
304
|
-
|
|
305
304
|
const nonce = await client.getCurrentNonce({address: validatedSenderAccount.address});
|
|
305
|
+
|
|
306
306
|
let estimatedGas: bigint;
|
|
307
307
|
try {
|
|
308
308
|
estimatedGas = await client.estimateTransactionGas({
|
|
@@ -311,58 +311,77 @@ const _sendTransaction = async ({
|
|
|
311
311
|
data: encodedData,
|
|
312
312
|
value: value,
|
|
313
313
|
});
|
|
314
|
-
} catch (
|
|
315
|
-
console.
|
|
314
|
+
} catch (err) {
|
|
315
|
+
console.error("Gas estimation failed, using default 200_000:", err);
|
|
316
316
|
estimatedGas = 200_000n;
|
|
317
317
|
}
|
|
318
|
-
const transactionRequest = await client.prepareTransactionRequest({
|
|
319
|
-
account: validatedSenderAccount,
|
|
320
|
-
to: client.chain.consensusMainContract?.address as Address,
|
|
321
|
-
data: encodedData,
|
|
322
|
-
type: "legacy",
|
|
323
|
-
nonce: Number(nonce),
|
|
324
|
-
value: value,
|
|
325
|
-
gas: estimatedGas,
|
|
326
|
-
});
|
|
327
318
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
319
|
+
// For local accounts, build transaction request directly to avoid viem's
|
|
320
|
+
// prepareTransactionRequest which calls eth_fillTransaction (unsupported by GenLayer RPC)
|
|
321
|
+
if (validatedSenderAccount?.type === "local") {
|
|
322
|
+
if (!validatedSenderAccount?.signTransaction) {
|
|
323
|
+
throw new Error("Account does not support signTransaction");
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const gasPriceHex = (await client.request({
|
|
327
|
+
method: "eth_gasPrice",
|
|
328
|
+
})) as string;
|
|
329
|
+
|
|
330
|
+
const transactionRequest = {
|
|
331
|
+
account: validatedSenderAccount,
|
|
332
|
+
to: client.chain.consensusMainContract?.address as Address,
|
|
332
333
|
data: encodedData,
|
|
333
|
-
|
|
334
|
-
|
|
334
|
+
type: "legacy" as const,
|
|
335
|
+
nonce: Number(nonce),
|
|
336
|
+
value: value,
|
|
337
|
+
gas: estimatedGas,
|
|
338
|
+
gasPrice: BigInt(gasPriceHex),
|
|
339
|
+
chainId: client.chain.id,
|
|
335
340
|
};
|
|
336
341
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
+
const serializedTransaction = await validatedSenderAccount.signTransaction(transactionRequest);
|
|
343
|
+
const txHash = await client.sendRawTransaction({serializedTransaction: serializedTransaction});
|
|
344
|
+
const receipt = await publicClient.waitForTransactionReceipt({hash: txHash});
|
|
342
345
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
const serializedTransaction = await validatedSenderAccount.signTransaction(transactionRequest);
|
|
346
|
+
if (receipt.status === "reverted") {
|
|
347
|
+
throw new Error("Transaction reverted");
|
|
348
|
+
}
|
|
348
349
|
|
|
349
|
-
|
|
350
|
+
const newTxEvents = parseEventLogs({
|
|
351
|
+
abi: client.chain.consensusMainContract?.abi as any,
|
|
352
|
+
eventName: "NewTransaction",
|
|
353
|
+
logs: receipt.logs,
|
|
354
|
+
}) as unknown as {args: {txId: `0x${string}`}}[];
|
|
350
355
|
|
|
351
|
-
|
|
356
|
+
if (newTxEvents.length === 0) {
|
|
357
|
+
throw new Error("Transaction not processed by consensus");
|
|
358
|
+
}
|
|
352
359
|
|
|
353
|
-
|
|
354
|
-
throw new Error("Transaction reverted");
|
|
360
|
+
return newTxEvents[0].args["txId"];
|
|
355
361
|
}
|
|
356
362
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
363
|
+
// For external wallets (e.g., MetaMask via AppKit), use prepareTransactionRequest
|
|
364
|
+
// which will route eth_* calls through the provider
|
|
365
|
+
const transactionRequest = await client.prepareTransactionRequest({
|
|
366
|
+
account: validatedSenderAccount,
|
|
367
|
+
to: client.chain.consensusMainContract?.address as Address,
|
|
368
|
+
data: encodedData,
|
|
369
|
+
type: "legacy",
|
|
370
|
+
nonce: Number(nonce),
|
|
371
|
+
value: value,
|
|
372
|
+
gas: estimatedGas,
|
|
373
|
+
});
|
|
362
374
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
375
|
+
const formattedRequest = {
|
|
376
|
+
from: transactionRequest.from,
|
|
377
|
+
to: transactionRequest.to,
|
|
378
|
+
data: encodedData,
|
|
379
|
+
value: transactionRequest.value ? `0x${transactionRequest.value.toString(16)}` : "0x0",
|
|
380
|
+
gas: transactionRequest.gas ? `0x${transactionRequest.gas.toString(16)}` : "0x5208",
|
|
381
|
+
};
|
|
366
382
|
|
|
367
|
-
return
|
|
383
|
+
return await client.request({
|
|
384
|
+
method: "eth_sendTransaction",
|
|
385
|
+
params: [formattedRequest as any],
|
|
386
|
+
});
|
|
368
387
|
};
|