genlayer-js 0.28.2 → 0.28.5

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.
@@ -2916,6 +2916,14 @@ type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<Client<Transpor
2916
2916
  txId: `0x${string}`;
2917
2917
  value?: bigint;
2918
2918
  }) => Promise<any>;
2919
+ finalizeTransaction: (args: {
2920
+ account?: Account;
2921
+ txId: `0x${string}`;
2922
+ }) => Promise<`0x${string}`>;
2923
+ finalizeIdlenessTxs: (args: {
2924
+ account?: Account;
2925
+ txIds: readonly `0x${string}`[];
2926
+ }) => Promise<`0x${string}`>;
2919
2927
  getMinAppealBond: (args: {
2920
2928
  txId: `0x${string}`;
2921
2929
  }) => Promise<bigint>;
@@ -2916,6 +2916,14 @@ type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<Client<Transpor
2916
2916
  txId: `0x${string}`;
2917
2917
  value?: bigint;
2918
2918
  }) => Promise<any>;
2919
+ finalizeTransaction: (args: {
2920
+ account?: Account;
2921
+ txId: `0x${string}`;
2922
+ }) => Promise<`0x${string}`>;
2923
+ finalizeIdlenessTxs: (args: {
2924
+ account?: Account;
2925
+ txIds: readonly `0x${string}`[];
2926
+ }) => Promise<`0x${string}`>;
2919
2927
  getMinAppealBond: (args: {
2920
2928
  txId: `0x${string}`;
2921
2929
  }) => Promise<bigint>;
package/dist/index.cjs CHANGED
@@ -530,10 +530,10 @@ function extractGenCallResult(result) {
530
530
  }
531
531
  var contractActions = (client, publicClient) => {
532
532
  return {
533
- /** Retrieves the source code of a deployed contract. Localnet only. */
533
+ /** Retrieves the source code of a deployed contract. Studio only. */
534
534
  getContractCode: async (address) => {
535
- if (client.chain.id !== _chunkPZEHAYIUcjs.localnet.id) {
536
- throw new Error(`getContractCode is only available on localnet (current chain: ${client.chain.name})`);
535
+ if (!client.chain.isStudio) {
536
+ throw new Error(`getContractCode is only available on Studio networks (current chain: ${client.chain.name})`);
537
537
  }
538
538
  const result = await client.request({
539
539
  method: "gen_getContractCode",
@@ -542,10 +542,10 @@ var contractActions = (client, publicClient) => {
542
542
  const codeBytes = b64ToArray(result);
543
543
  return new TextDecoder().decode(codeBytes);
544
544
  },
545
- /** Gets the schema (methods and constructor) of a deployed contract. Localnet only. */
545
+ /** Gets the schema (methods and constructor) of a deployed contract. Studio only. */
546
546
  getContractSchema: async (address) => {
547
- if (client.chain.id !== _chunkPZEHAYIUcjs.localnet.id) {
548
- throw new Error(`getContractSchema is only available on localnet (current chain: ${client.chain.name})`);
547
+ if (!client.chain.isStudio) {
548
+ throw new Error(`getContractSchema is only available on Studio networks (current chain: ${client.chain.name})`);
549
549
  }
550
550
  const schema = await client.request({
551
551
  method: "gen_getContractSchema",
@@ -553,10 +553,10 @@ var contractActions = (client, publicClient) => {
553
553
  });
554
554
  return schema;
555
555
  },
556
- /** Generates a schema for contract code without deploying it. Localnet only. */
556
+ /** Generates a schema for contract code without deploying it. Studio only. */
557
557
  getContractSchemaForCode: async (contractCode) => {
558
- if (client.chain.id !== _chunkPZEHAYIUcjs.localnet.id) {
559
- throw new Error(`getContractSchema is only available on localnet (current chain: ${client.chain.name})`);
558
+ if (!client.chain.isStudio) {
559
+ throw new Error(`getContractSchemaForCode is only available on Studio networks (current chain: ${client.chain.name})`);
560
560
  }
561
561
  const schema = await client.request({
562
562
  method: "gen_getContractSchemaForCode",
@@ -792,61 +792,52 @@ var contractActions = (client, publicClient) => {
792
792
  }
793
793
  const senderAccount = account || client.account;
794
794
  const encodedData = _encodeSubmitAppealData({ client, txId });
795
- const validatedAccount = validateAccount(senderAccount);
796
- if (!_optionalChain([client, 'access', _35 => _35.chain, 'access', _36 => _36.consensusMainContract, 'optionalAccess', _37 => _37.address])) {
797
- throw new Error("Consensus main contract not initialized.");
798
- }
799
- const nonce = await client.getCurrentNonce({ address: validatedAccount.address });
800
- let estimatedGas;
801
- try {
802
- estimatedGas = await client.estimateTransactionGas({
803
- to: client.chain.consensusMainContract.address,
804
- data: encodedData,
805
- value,
806
- nonce
807
- });
808
- } catch (err) {
809
- console.error("Gas estimation failed, using default 200_000:", err);
810
- estimatedGas = 200000n;
811
- }
812
- const gasPriceHex = await client.request({ method: "eth_gasPrice" });
813
- const txRequest = {
814
- account: validatedAccount,
815
- to: client.chain.consensusMainContract.address,
816
- data: encodedData,
795
+ await _sendConsensusCall({
796
+ client,
797
+ publicClient,
798
+ encodedData,
799
+ senderAccount,
817
800
  value,
818
- gas: estimatedGas,
819
- gasPrice: BigInt(gasPriceHex),
820
- nonce,
821
- chainId: client.chain.id
822
- };
823
- if (validatedAccount.type === "local") {
824
- if (!validatedAccount.signTransaction) {
825
- throw new Error("Local account does not support signTransaction.");
826
- }
827
- const serializedTransaction = await validatedAccount.signTransaction(txRequest);
828
- const evmHash = await client.sendRawTransaction({ serializedTransaction });
829
- const receipt = await publicClient.waitForTransactionReceipt({ hash: evmHash });
830
- if (receipt.status === "reverted") {
831
- throw new Error(`Appeal reverted: EVM tx ${evmHash}`);
832
- }
833
- } else {
834
- const evmHash = await client.request({
835
- method: "eth_sendTransaction",
836
- params: [{
837
- from: validatedAccount.address,
838
- to: client.chain.consensusMainContract.address,
839
- data: encodedData,
840
- value: value ? `0x${value.toString(16)}` : void 0,
841
- gas: `0x${estimatedGas.toString(16)}`
842
- }]
843
- });
844
- const receipt = await publicClient.waitForTransactionReceipt({ hash: evmHash });
845
- if (receipt.status === "reverted") {
846
- throw new Error(`Appeal reverted: EVM tx ${evmHash}`);
847
- }
848
- }
801
+ operationName: "Appeal"
802
+ });
849
803
  return txId;
804
+ },
805
+ /** Finalizes a single GenLayer transaction that is ready to be finalized. Returns the EVM transaction hash. */
806
+ finalizeTransaction: async (args) => {
807
+ const { account, txId } = args;
808
+ const senderAccount = account || client.account;
809
+ const encodedData = _viem.encodeFunctionData.call(void 0, {
810
+ abi: _optionalChain([client, 'access', _35 => _35.chain, 'access', _36 => _36.consensusMainContract, 'optionalAccess', _37 => _37.abi]),
811
+ functionName: "finalizeTransaction",
812
+ args: [txId]
813
+ });
814
+ return _sendConsensusCall({
815
+ client,
816
+ publicClient,
817
+ encodedData,
818
+ senderAccount,
819
+ operationName: "Finalize"
820
+ });
821
+ },
822
+ /** Batch-finalizes idle GenLayer transactions (those stuck without progressing). Returns the EVM transaction hash. */
823
+ finalizeIdlenessTxs: async (args) => {
824
+ const { account, txIds } = args;
825
+ if (txIds.length === 0) {
826
+ throw new Error("finalizeIdlenessTxs requires at least one txId.");
827
+ }
828
+ const senderAccount = account || client.account;
829
+ const encodedData = _viem.encodeFunctionData.call(void 0, {
830
+ abi: _optionalChain([client, 'access', _38 => _38.chain, 'access', _39 => _39.consensusMainContract, 'optionalAccess', _40 => _40.abi]),
831
+ functionName: "finalizeIdlenessTxs",
832
+ args: [txIds]
833
+ });
834
+ return _sendConsensusCall({
835
+ client,
836
+ publicClient,
837
+ encodedData,
838
+ senderAccount,
839
+ operationName: "Finalize idleness"
840
+ });
850
841
  }
851
842
  };
852
843
  };
@@ -911,7 +902,7 @@ var getAddTransactionInputCount = (abi) => {
911
902
  const candidate = item;
912
903
  return candidate.type === "function" && candidate.name === "addTransaction";
913
904
  });
914
- return Array.isArray(_optionalChain([addTransactionFunction, 'optionalAccess', _38 => _38.inputs])) ? addTransactionFunction.inputs.length : 0;
905
+ return Array.isArray(_optionalChain([addTransactionFunction, 'optionalAccess', _41 => _41.inputs])) ? addTransactionFunction.inputs.length : 0;
915
906
  };
916
907
  var _encodeAddTransactionData = ({
917
908
  client,
@@ -938,7 +929,7 @@ var _encodeAddTransactionData = ({
938
929
  functionName: "addTransaction",
939
930
  args: [...addTransactionArgs, 0n]
940
931
  });
941
- if (getAddTransactionInputCount(_optionalChain([client, 'access', _39 => _39.chain, 'access', _40 => _40.consensusMainContract, 'optionalAccess', _41 => _41.abi])) >= 6) {
932
+ if (getAddTransactionInputCount(_optionalChain([client, 'access', _42 => _42.chain, 'access', _43 => _43.consensusMainContract, 'optionalAccess', _44 => _44.abi])) >= 6) {
942
933
  return {
943
934
  primaryEncodedData: encodedDataV6,
944
935
  fallbackEncodedData: encodedDataV5
@@ -954,11 +945,74 @@ var _encodeSubmitAppealData = ({
954
945
  txId
955
946
  }) => {
956
947
  return _viem.encodeFunctionData.call(void 0, {
957
- abi: _optionalChain([client, 'access', _42 => _42.chain, 'access', _43 => _43.consensusMainContract, 'optionalAccess', _44 => _44.abi]),
948
+ abi: _optionalChain([client, 'access', _45 => _45.chain, 'access', _46 => _46.consensusMainContract, 'optionalAccess', _47 => _47.abi]),
958
949
  functionName: "submitAppeal",
959
950
  args: [txId]
960
951
  });
961
952
  };
953
+ var _sendConsensusCall = async ({
954
+ client,
955
+ publicClient,
956
+ encodedData,
957
+ senderAccount,
958
+ value = 0n,
959
+ operationName = "Consensus call"
960
+ }) => {
961
+ if (!_optionalChain([client, 'access', _48 => _48.chain, 'access', _49 => _49.consensusMainContract, 'optionalAccess', _50 => _50.address])) {
962
+ throw new Error("Consensus main contract not initialized.");
963
+ }
964
+ const validatedAccount = validateAccount(senderAccount);
965
+ const nonce = await client.getCurrentNonce({ address: validatedAccount.address });
966
+ let estimatedGas;
967
+ try {
968
+ estimatedGas = await client.estimateTransactionGas({
969
+ to: client.chain.consensusMainContract.address,
970
+ data: encodedData,
971
+ value
972
+ });
973
+ } catch (err) {
974
+ console.error("Gas estimation failed, using default 200_000:", err);
975
+ estimatedGas = 200000n;
976
+ }
977
+ const gasPriceHex = await client.request({ method: "eth_gasPrice" });
978
+ if (validatedAccount.type === "local") {
979
+ if (!validatedAccount.signTransaction) {
980
+ throw new Error("Local account does not support signTransaction.");
981
+ }
982
+ const txRequest = {
983
+ account: validatedAccount,
984
+ to: client.chain.consensusMainContract.address,
985
+ data: encodedData,
986
+ value,
987
+ gas: estimatedGas,
988
+ gasPrice: BigInt(gasPriceHex),
989
+ nonce,
990
+ chainId: client.chain.id
991
+ };
992
+ const serializedTransaction = await validatedAccount.signTransaction(txRequest);
993
+ const evmHash2 = await client.sendRawTransaction({ serializedTransaction });
994
+ const receipt2 = await publicClient.waitForTransactionReceipt({ hash: evmHash2 });
995
+ if (receipt2.status === "reverted") {
996
+ throw new Error(`${operationName} reverted: EVM tx ${evmHash2}`);
997
+ }
998
+ return evmHash2;
999
+ }
1000
+ const evmHash = await client.request({
1001
+ method: "eth_sendTransaction",
1002
+ params: [{
1003
+ from: validatedAccount.address,
1004
+ to: client.chain.consensusMainContract.address,
1005
+ data: encodedData,
1006
+ value: value ? `0x${value.toString(16)}` : void 0,
1007
+ gas: `0x${estimatedGas.toString(16)}`
1008
+ }]
1009
+ });
1010
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: evmHash });
1011
+ if (receipt.status === "reverted") {
1012
+ throw new Error(`${operationName} reverted: EVM tx ${evmHash}`);
1013
+ }
1014
+ return evmHash;
1015
+ };
962
1016
  var isAddTransactionAbiMismatchError = (error) => {
963
1017
  const seen = /* @__PURE__ */ new WeakSet();
964
1018
  const serializedError = typeof error === "object" && error !== null ? JSON.stringify(error, (_key, value) => {
@@ -975,9 +1029,9 @@ var isAddTransactionAbiMismatchError = (error) => {
975
1029
  }) : "";
976
1030
  const errorObject = error;
977
1031
  const errorMessage = [
978
- _optionalChain([errorObject, 'optionalAccess', _45 => _45.shortMessage]),
979
- _optionalChain([errorObject, 'optionalAccess', _46 => _46.details]),
980
- _optionalChain([errorObject, 'optionalAccess', _47 => _47.message]),
1032
+ _optionalChain([errorObject, 'optionalAccess', _51 => _51.shortMessage]),
1033
+ _optionalChain([errorObject, 'optionalAccess', _52 => _52.details]),
1034
+ _optionalChain([errorObject, 'optionalAccess', _53 => _53.message]),
981
1035
  serializedError,
982
1036
  String(_nullishCoalesce(error, () => ( "")))
983
1037
  ].filter(Boolean).join(" ").toLowerCase();
@@ -985,7 +1039,7 @@ var isAddTransactionAbiMismatchError = (error) => {
985
1039
  };
986
1040
  var extractTxIdFromLogs = (client, logs) => {
987
1041
  const newTxEvents = _viem.parseEventLogs.call(void 0, {
988
- abi: _optionalChain([client, 'access', _48 => _48.chain, 'access', _49 => _49.consensusMainContract, 'optionalAccess', _50 => _50.abi]),
1042
+ abi: _optionalChain([client, 'access', _54 => _54.chain, 'access', _55 => _55.consensusMainContract, 'optionalAccess', _56 => _56.abi]),
989
1043
  eventName: "NewTransaction",
990
1044
  logs
991
1045
  });
@@ -1010,7 +1064,7 @@ var _sendTransaction = async ({
1010
1064
  senderAccount,
1011
1065
  value = 0n
1012
1066
  }) => {
1013
- if (!_optionalChain([client, 'access', _51 => _51.chain, 'access', _52 => _52.consensusMainContract, 'optionalAccess', _53 => _53.address])) {
1067
+ if (!_optionalChain([client, 'access', _57 => _57.chain, 'access', _58 => _58.consensusMainContract, 'optionalAccess', _59 => _59.address])) {
1014
1068
  throw new Error(`Consensus main contract address not found in chain config for "${client.chain.name}".`);
1015
1069
  }
1016
1070
  const validatedSenderAccount = validateAccount(senderAccount);
@@ -1020,7 +1074,7 @@ var _sendTransaction = async ({
1020
1074
  try {
1021
1075
  estimatedGas = await client.estimateTransactionGas({
1022
1076
  from: validatedSenderAccount.address,
1023
- to: _optionalChain([client, 'access', _54 => _54.chain, 'access', _55 => _55.consensusMainContract, 'optionalAccess', _56 => _56.address]),
1077
+ to: _optionalChain([client, 'access', _60 => _60.chain, 'access', _61 => _61.consensusMainContract, 'optionalAccess', _62 => _62.address]),
1024
1078
  data: encodedDataForSend,
1025
1079
  value
1026
1080
  });
@@ -1028,8 +1082,8 @@ var _sendTransaction = async ({
1028
1082
  console.error("Gas estimation failed, using default 200_000:", err);
1029
1083
  estimatedGas = 200000n;
1030
1084
  }
1031
- if (_optionalChain([validatedSenderAccount, 'optionalAccess', _57 => _57.type]) === "local") {
1032
- if (!_optionalChain([validatedSenderAccount, 'optionalAccess', _58 => _58.signTransaction])) {
1085
+ if (_optionalChain([validatedSenderAccount, 'optionalAccess', _63 => _63.type]) === "local") {
1086
+ if (!_optionalChain([validatedSenderAccount, 'optionalAccess', _64 => _64.signTransaction])) {
1033
1087
  throw new Error("Local account does not support signTransaction. Use a private key account created via privateKeyToAccount().");
1034
1088
  }
1035
1089
  const gasPriceHex2 = await client.request({
@@ -1037,7 +1091,7 @@ var _sendTransaction = async ({
1037
1091
  });
1038
1092
  const transactionRequest = {
1039
1093
  account: validatedSenderAccount,
1040
- to: _optionalChain([client, 'access', _59 => _59.chain, 'access', _60 => _60.consensusMainContract, 'optionalAccess', _61 => _61.address]),
1094
+ to: _optionalChain([client, 'access', _65 => _65.chain, 'access', _66 => _66.consensusMainContract, 'optionalAccess', _67 => _67.address]),
1041
1095
  data: encodedDataForSend,
1042
1096
  type: "legacy",
1043
1097
  nonce: Number(nonce),
@@ -1050,7 +1104,7 @@ var _sendTransaction = async ({
1050
1104
  const txHash = await client.sendRawTransaction({ serializedTransaction });
1051
1105
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1052
1106
  if (receipt.status === "reverted") {
1053
- throw new Error(`Transaction reverted: EVM tx ${txHash} to consensus contract ${_optionalChain([client, 'access', _62 => _62.chain, 'access', _63 => _63.consensusMainContract, 'optionalAccess', _64 => _64.address])} was reverted.`);
1107
+ throw new Error(`Transaction reverted: EVM tx ${txHash} to consensus contract ${_optionalChain([client, 'access', _68 => _68.chain, 'access', _69 => _69.consensusMainContract, 'optionalAccess', _70 => _70.address])} was reverted.`);
1054
1108
  }
1055
1109
  const txId = extractTxIdFromLogs(client, receipt.logs);
1056
1110
  if (!txId) {
@@ -1074,7 +1128,7 @@ var _sendTransaction = async ({
1074
1128
  const nonceBigInt = typeof nonce === "bigint" ? nonce : typeof nonce === "string" ? BigInt(nonce) : BigInt(Number(nonce));
1075
1129
  const formattedRequest = {
1076
1130
  from: validatedSenderAccount.address,
1077
- to: _optionalChain([client, 'access', _65 => _65.chain, 'access', _66 => _66.consensusMainContract, 'optionalAccess', _67 => _67.address]),
1131
+ to: _optionalChain([client, 'access', _71 => _71.chain, 'access', _72 => _72.consensusMainContract, 'optionalAccess', _73 => _73.address]),
1078
1132
  data: encodedDataForSend,
1079
1133
  value: `0x${value.toString(16)}`,
1080
1134
  gas: `0x${estimatedGas.toString(16)}`,
@@ -1088,9 +1142,12 @@ var _sendTransaction = async ({
1088
1142
  method: "eth_sendTransaction",
1089
1143
  params: [formattedRequest]
1090
1144
  });
1145
+ if (client.chain.isStudio) {
1146
+ return evmTxHash;
1147
+ }
1091
1148
  const externalReceipt = await publicClient.waitForTransactionReceipt({ hash: evmTxHash });
1092
1149
  if (externalReceipt.status === "reverted") {
1093
- throw new Error(`Transaction reverted: EVM tx ${evmTxHash} to consensus contract ${_optionalChain([client, 'access', _68 => _68.chain, 'access', _69 => _69.consensusMainContract, 'optionalAccess', _70 => _70.address])} was reverted.`);
1150
+ throw new Error(`Transaction reverted: EVM tx ${evmTxHash} to consensus contract ${_optionalChain([client, 'access', _74 => _74.chain, 'access', _75 => _75.consensusMainContract, 'optionalAccess', _76 => _76.address])} was reverted.`);
1094
1151
  }
1095
1152
  const externalTxId = extractTxIdFromLogs(client, externalReceipt.logs);
1096
1153
  if (!externalTxId) {
@@ -1215,7 +1272,7 @@ var decodeTransaction = (tx) => {
1215
1272
  txData,
1216
1273
  txDataDecoded,
1217
1274
  currentTimestamp: tx.currentTimestamp.toString(),
1218
- numOfInitialValidators: _nullishCoalesce(_optionalChain([numOfInitialValidators, 'optionalAccess', _71 => _71.toString, 'call', _72 => _72()]), () => ( "0")),
1275
+ numOfInitialValidators: _nullishCoalesce(_optionalChain([numOfInitialValidators, 'optionalAccess', _77 => _77.toString, 'call', _78 => _78()]), () => ( "0")),
1219
1276
  txSlot: tx.txSlot.toString(),
1220
1277
  createdTimestamp: tx.createdTimestamp.toString(),
1221
1278
  lastVoteTimestamp: tx.lastVoteTimestamp.toString(),
@@ -1223,9 +1280,9 @@ var decodeTransaction = (tx) => {
1223
1280
  numOfRounds: tx.numOfRounds.toString(),
1224
1281
  readStateBlockRange: {
1225
1282
  ...tx.readStateBlockRange,
1226
- activationBlock: _nullishCoalesce(_optionalChain([tx, 'access', _73 => _73.readStateBlockRange, 'optionalAccess', _74 => _74.activationBlock, 'optionalAccess', _75 => _75.toString, 'call', _76 => _76()]), () => ( "0")),
1227
- processingBlock: _nullishCoalesce(_optionalChain([tx, 'access', _77 => _77.readStateBlockRange, 'optionalAccess', _78 => _78.processingBlock, 'optionalAccess', _79 => _79.toString, 'call', _80 => _80()]), () => ( "0")),
1228
- proposalBlock: _nullishCoalesce(_optionalChain([tx, 'access', _81 => _81.readStateBlockRange, 'optionalAccess', _82 => _82.proposalBlock, 'optionalAccess', _83 => _83.toString, 'call', _84 => _84()]), () => ( "0"))
1283
+ activationBlock: _nullishCoalesce(_optionalChain([tx, 'access', _79 => _79.readStateBlockRange, 'optionalAccess', _80 => _80.activationBlock, 'optionalAccess', _81 => _81.toString, 'call', _82 => _82()]), () => ( "0")),
1284
+ processingBlock: _nullishCoalesce(_optionalChain([tx, 'access', _83 => _83.readStateBlockRange, 'optionalAccess', _84 => _84.processingBlock, 'optionalAccess', _85 => _85.toString, 'call', _86 => _86()]), () => ( "0")),
1285
+ proposalBlock: _nullishCoalesce(_optionalChain([tx, 'access', _87 => _87.readStateBlockRange, 'optionalAccess', _88 => _88.proposalBlock, 'optionalAccess', _89 => _89.toString, 'call', _90 => _90()]), () => ( "0"))
1229
1286
  },
1230
1287
  statusName: _chunkGJXSECNHcjs.transactionsStatusNumberToName[String(tx.status)],
1231
1288
  resultName: _chunkGJXSECNHcjs.transactionResultNumberToName[String(tx.result)],
@@ -1233,13 +1290,13 @@ var decodeTransaction = (tx) => {
1233
1290
  txExecutionResultName: tx.txExecutionResult !== void 0 ? _chunkGJXSECNHcjs.executionResultNumberToName[String(tx.txExecutionResult)] : void 0,
1234
1291
  lastRound: {
1235
1292
  ...tx.lastRound,
1236
- round: _nullishCoalesce(_optionalChain([tx, 'access', _85 => _85.lastRound, 'optionalAccess', _86 => _86.round, 'optionalAccess', _87 => _87.toString, 'call', _88 => _88()]), () => ( "0")),
1237
- leaderIndex: _nullishCoalesce(_optionalChain([tx, 'access', _89 => _89.lastRound, 'optionalAccess', _90 => _90.leaderIndex, 'optionalAccess', _91 => _91.toString, 'call', _92 => _92()]), () => ( "0")),
1238
- votesCommitted: _nullishCoalesce(_optionalChain([tx, 'access', _93 => _93.lastRound, 'optionalAccess', _94 => _94.votesCommitted, 'optionalAccess', _95 => _95.toString, 'call', _96 => _96()]), () => ( "0")),
1239
- votesRevealed: _nullishCoalesce(_optionalChain([tx, 'access', _97 => _97.lastRound, 'optionalAccess', _98 => _98.votesRevealed, 'optionalAccess', _99 => _99.toString, 'call', _100 => _100()]), () => ( "0")),
1240
- appealBond: _nullishCoalesce(_optionalChain([tx, 'access', _101 => _101.lastRound, 'optionalAccess', _102 => _102.appealBond, 'optionalAccess', _103 => _103.toString, 'call', _104 => _104()]), () => ( "0")),
1241
- rotationsLeft: _nullishCoalesce(_optionalChain([tx, 'access', _105 => _105.lastRound, 'optionalAccess', _106 => _106.rotationsLeft, 'optionalAccess', _107 => _107.toString, 'call', _108 => _108()]), () => ( "0")),
1242
- validatorVotesName: (_nullishCoalesce(_optionalChain([tx, 'access', _109 => _109.lastRound, 'optionalAccess', _110 => _110.validatorVotes]), () => ( []))).map(
1293
+ round: _nullishCoalesce(_optionalChain([tx, 'access', _91 => _91.lastRound, 'optionalAccess', _92 => _92.round, 'optionalAccess', _93 => _93.toString, 'call', _94 => _94()]), () => ( "0")),
1294
+ leaderIndex: _nullishCoalesce(_optionalChain([tx, 'access', _95 => _95.lastRound, 'optionalAccess', _96 => _96.leaderIndex, 'optionalAccess', _97 => _97.toString, 'call', _98 => _98()]), () => ( "0")),
1295
+ votesCommitted: _nullishCoalesce(_optionalChain([tx, 'access', _99 => _99.lastRound, 'optionalAccess', _100 => _100.votesCommitted, 'optionalAccess', _101 => _101.toString, 'call', _102 => _102()]), () => ( "0")),
1296
+ votesRevealed: _nullishCoalesce(_optionalChain([tx, 'access', _103 => _103.lastRound, 'optionalAccess', _104 => _104.votesRevealed, 'optionalAccess', _105 => _105.toString, 'call', _106 => _106()]), () => ( "0")),
1297
+ appealBond: _nullishCoalesce(_optionalChain([tx, 'access', _107 => _107.lastRound, 'optionalAccess', _108 => _108.appealBond, 'optionalAccess', _109 => _109.toString, 'call', _110 => _110()]), () => ( "0")),
1298
+ rotationsLeft: _nullishCoalesce(_optionalChain([tx, 'access', _111 => _111.lastRound, 'optionalAccess', _112 => _112.rotationsLeft, 'optionalAccess', _113 => _113.toString, 'call', _114 => _114()]), () => ( "0")),
1299
+ validatorVotesName: (_nullishCoalesce(_optionalChain([tx, 'access', _115 => _115.lastRound, 'optionalAccess', _116 => _116.validatorVotes]), () => ( []))).map(
1243
1300
  (vote) => _chunkGJXSECNHcjs.voteTypeNumberToName[String(vote)]
1244
1301
  )
1245
1302
  }
@@ -1321,7 +1378,7 @@ var simplifyTransactionReceipt = (tx) => {
1321
1378
  var decodeLocalnetTransaction = (tx) => {
1322
1379
  if (!tx.data) return tx;
1323
1380
  try {
1324
- const leaderReceipt = _optionalChain([tx, 'access', _111 => _111.consensus_data, 'optionalAccess', _112 => _112.leader_receipt]);
1381
+ const leaderReceipt = _optionalChain([tx, 'access', _117 => _117.consensus_data, 'optionalAccess', _118 => _118.leader_receipt]);
1325
1382
  if (leaderReceipt) {
1326
1383
  const receipts = Array.isArray(leaderReceipt) ? leaderReceipt : [leaderReceipt];
1327
1384
  receipts.forEach((receipt) => {
@@ -1352,7 +1409,7 @@ var decodeLocalnetTransaction = (tx) => {
1352
1409
  }
1353
1410
  });
1354
1411
  }
1355
- if (_optionalChain([tx, 'access', _113 => _113.data, 'optionalAccess', _114 => _114.calldata]) && typeof tx.data.calldata === "string") {
1412
+ if (_optionalChain([tx, 'access', _119 => _119.data, 'optionalAccess', _120 => _120.calldata]) && typeof tx.data.calldata === "string") {
1356
1413
  tx.data.calldata = {
1357
1414
  base64: tx.data.calldata,
1358
1415
  ...calldataToUserFriendlyJson(b64ToArray(tx.data.calldata))
@@ -1384,7 +1441,7 @@ var receiptActions = (client, publicClient) => ({
1384
1441
  const requestedStatus = _chunkGJXSECNHcjs.transactionsStatusNameToNumber[status];
1385
1442
  if (transactionStatusString === requestedStatus || status === "ACCEPTED" /* ACCEPTED */ && _chunkGJXSECNHcjs.isDecidedState.call(void 0, transactionStatusString)) {
1386
1443
  let finalTransaction = transaction;
1387
- if (client.chain.id === _chunkPZEHAYIUcjs.localnet.id) {
1444
+ if (client.chain.isStudio) {
1388
1445
  finalTransaction = decodeLocalnetTransaction(transaction);
1389
1446
  }
1390
1447
  if (!fullTransaction) {
@@ -1415,8 +1472,8 @@ var transactionActions = (client, publicClient) => ({
1415
1472
  transaction2.statusName = localnetStatus;
1416
1473
  return decodeLocalnetTransaction(transaction2);
1417
1474
  }
1418
- const contractAddress = _optionalChain([client, 'access', _115 => _115.chain, 'access', _116 => _116.consensusDataContract, 'optionalAccess', _117 => _117.address]);
1419
- const contractAbi = _optionalChain([client, 'access', _118 => _118.chain, 'access', _119 => _119.consensusDataContract, 'optionalAccess', _120 => _120.abi]);
1475
+ const contractAddress = _optionalChain([client, 'access', _121 => _121.chain, 'access', _122 => _122.consensusDataContract, 'optionalAccess', _123 => _123.address]);
1476
+ const contractAbi = _optionalChain([client, 'access', _124 => _124.chain, 'access', _125 => _125.consensusDataContract, 'optionalAccess', _126 => _126.abi]);
1420
1477
  const [txDataRaw, allDataRaw] = await Promise.all([
1421
1478
  publicClient.readContract({
1422
1479
  address: contractAddress,
@@ -1446,12 +1503,12 @@ var transactionActions = (client, publicClient) => ({
1446
1503
  return _nullishCoalesce(tx2.triggered_transactions, () => ( []));
1447
1504
  }
1448
1505
  const tx = await transactionActions(client, publicClient).getTransaction({ hash });
1449
- const proposalBlock = BigInt(_nullishCoalesce(_optionalChain([tx, 'access', _121 => _121.readStateBlockRange, 'optionalAccess', _122 => _122.proposalBlock]), () => ( "0")));
1506
+ const proposalBlock = BigInt(_nullishCoalesce(_optionalChain([tx, 'access', _127 => _127.readStateBlockRange, 'optionalAccess', _128 => _128.proposalBlock]), () => ( "0")));
1450
1507
  if (proposalBlock === BigInt(0)) return [];
1451
1508
  const scanRange = BigInt(100);
1452
1509
  const latestBlock = await publicClient.getBlockNumber();
1453
1510
  const toBlock = proposalBlock + scanRange < latestBlock ? proposalBlock + scanRange : latestBlock;
1454
- const consensusAddress = _optionalChain([client, 'access', _123 => _123.chain, 'access', _124 => _124.consensusMainContract, 'optionalAccess', _125 => _125.address]);
1511
+ const consensusAddress = _optionalChain([client, 'access', _129 => _129.chain, 'access', _130 => _130.consensusMainContract, 'optionalAccess', _131 => _131.address]);
1455
1512
  const internalMessageProcessedTopic = _viem.keccak256.call(void 0, _viem.stringToBytes.call(void 0, "InternalMessageProcessed(bytes32,address,address)"));
1456
1513
  const logs = await publicClient.getLogs({
1457
1514
  address: consensusAddress,
@@ -1500,8 +1557,8 @@ var transactionActions = (client, publicClient) => ({
1500
1557
  },
1501
1558
  /** Returns the queue slot position of a transaction in the pending queue. */
1502
1559
  getTransactionQueuePosition: async ({ hash }) => {
1503
- const consensusAddress = _optionalChain([client, 'access', _126 => _126.chain, 'access', _127 => _127.consensusMainContract, 'optionalAccess', _128 => _128.address]);
1504
- const consensusAbi = _optionalChain([client, 'access', _129 => _129.chain, 'access', _130 => _130.consensusMainContract, 'optionalAccess', _131 => _131.abi]);
1560
+ const consensusAddress = _optionalChain([client, 'access', _132 => _132.chain, 'access', _133 => _133.consensusMainContract, 'optionalAccess', _134 => _134.address]);
1561
+ const consensusAbi = _optionalChain([client, 'access', _135 => _135.chain, 'access', _136 => _136.consensusMainContract, 'optionalAccess', _137 => _137.abi]);
1505
1562
  const queuesAddress = await publicClient.readContract({
1506
1563
  address: consensusAddress,
1507
1564
  abi: consensusAbi,
@@ -1527,7 +1584,7 @@ var transactionActions = (client, publicClient) => ({
1527
1584
  /** Estimates gas required for a transaction. */
1528
1585
  estimateTransactionGas: async (transactionParams) => {
1529
1586
  const formattedParams = {
1530
- from: transactionParams.from || _optionalChain([client, 'access', _132 => _132.account, 'optionalAccess', _133 => _133.address]),
1587
+ from: transactionParams.from || _optionalChain([client, 'access', _138 => _138.account, 'optionalAccess', _139 => _139.address]),
1531
1588
  to: transactionParams.to,
1532
1589
  data: transactionParams.data || "0x",
1533
1590
  value: transactionParams.value ? `0x${transactionParams.value.toString(16)}` : "0x0"
@@ -1570,7 +1627,7 @@ var connect = async (client, network = "studionet", snapSource = "npm") => {
1570
1627
  chainName: selectedNetwork.name,
1571
1628
  rpcUrls: selectedNetwork.rpcUrls.default.http,
1572
1629
  nativeCurrency: selectedNetwork.nativeCurrency,
1573
- blockExplorerUrls: [_optionalChain([selectedNetwork, 'access', _134 => _134.blockExplorers, 'optionalAccess', _135 => _135.default, 'access', _136 => _136.url])]
1630
+ blockExplorerUrls: [_optionalChain([selectedNetwork, 'access', _140 => _140.blockExplorers, 'optionalAccess', _141 => _141.default, 'access', _142 => _142.url])]
1574
1631
  };
1575
1632
  const currentChainId = await window.ethereum.request({ method: "eth_chainId" });
1576
1633
  if (currentChainId !== chainIdHex) {
@@ -1604,10 +1661,10 @@ var metamaskClient = async (snapSource = "npm") => {
1604
1661
  }
1605
1662
  const isFlask = async () => {
1606
1663
  try {
1607
- const clientVersion = await _optionalChain([window, 'access', _137 => _137.ethereum, 'optionalAccess', _138 => _138.request, 'call', _139 => _139({
1664
+ const clientVersion = await _optionalChain([window, 'access', _143 => _143.ethereum, 'optionalAccess', _144 => _144.request, 'call', _145 => _145({
1608
1665
  method: "web3_clientVersion"
1609
1666
  })]);
1610
- return _optionalChain([clientVersion, 'optionalAccess', _140 => _140.includes, 'call', _141 => _141("flask")]);
1667
+ return _optionalChain([clientVersion, 'optionalAccess', _146 => _146.includes, 'call', _147 => _147("flask")]);
1611
1668
  } catch (error) {
1612
1669
  console.error("Error detecting Flask:", error);
1613
1670
  return false;
@@ -1615,7 +1672,7 @@ var metamaskClient = async (snapSource = "npm") => {
1615
1672
  };
1616
1673
  const installedSnaps = async () => {
1617
1674
  try {
1618
- return await _optionalChain([window, 'access', _142 => _142.ethereum, 'optionalAccess', _143 => _143.request, 'call', _144 => _144({
1675
+ return await _optionalChain([window, 'access', _148 => _148.ethereum, 'optionalAccess', _149 => _149.request, 'call', _150 => _150({
1619
1676
  method: "wallet_getSnaps"
1620
1677
  })]);
1621
1678
  } catch (error) {
@@ -1702,7 +1759,7 @@ function extractRevertReason(err) {
1702
1759
  }
1703
1760
  const revertError = err.walk((e) => e instanceof _viem.ContractFunctionRevertedError);
1704
1761
  if (revertError instanceof _viem.ContractFunctionRevertedError) {
1705
- if (_optionalChain([revertError, 'access', _145 => _145.data, 'optionalAccess', _146 => _146.errorName])) {
1762
+ if (_optionalChain([revertError, 'access', _151 => _151.data, 'optionalAccess', _152 => _152.errorName])) {
1706
1763
  return revertError.data.errorName;
1707
1764
  }
1708
1765
  return revertError.reason || "Unknown reason";
@@ -1790,7 +1847,7 @@ var stakingActions = (client, publicClient) => {
1790
1847
  };
1791
1848
  const getStakingAddress = () => {
1792
1849
  const stakingConfig = client.chain.stakingContract;
1793
- if (!_optionalChain([stakingConfig, 'optionalAccess', _147 => _147.address]) || stakingConfig.address === "0x0000000000000000000000000000000000000000") {
1850
+ if (!_optionalChain([stakingConfig, 'optionalAccess', _153 => _153.address]) || stakingConfig.address === "0x0000000000000000000000000000000000000000") {
1794
1851
  throw new Error("Staking is not supported on studio-based networks. Use testnet-asimov for staking operations.");
1795
1852
  }
1796
1853
  return stakingConfig.address;
@@ -1875,10 +1932,10 @@ var stakingActions = (client, publicClient) => {
1875
1932
  },
1876
1933
  /** Claims pending validator withdrawals. */
1877
1934
  validatorClaim: async (options) => {
1878
- if (!_optionalChain([options, 'optionalAccess', _148 => _148.validator]) && !client.account) {
1935
+ if (!_optionalChain([options, 'optionalAccess', _154 => _154.validator]) && !client.account) {
1879
1936
  throw new Error("Either provide validator address or initialize client with an account");
1880
1937
  }
1881
- const validatorAddress = _optionalChain([options, 'optionalAccess', _149 => _149.validator]) || client.account.address;
1938
+ const validatorAddress = _optionalChain([options, 'optionalAccess', _155 => _155.validator]) || client.account.address;
1882
1939
  const data = _viem.encodeFunctionData.call(void 0, {
1883
1940
  abi: _chunkPZEHAYIUcjs.STAKING_ABI,
1884
1941
  functionName: "validatorClaim",
@@ -2264,6 +2321,7 @@ var PROVIDER_METHODS = /* @__PURE__ */ new Set([
2264
2321
  "eth_signTypedData_v4"
2265
2322
  ]);
2266
2323
  var assertChainMatch = async (provider, chainConfig) => {
2324
+ if (chainConfig.isStudio) return;
2267
2325
  const expectedChainIdHex = `0x${chainConfig.id.toString(16)}`;
2268
2326
  try {
2269
2327
  const currentChainId = await provider.request({ method: "eth_chainId" });
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as viem from 'viem';
2
2
  import { Account, Address, Hex } from 'viem';
3
3
  import { G as GenLayerChain } from './chains-D6DgvIVA.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, d as ContractSchema } from './index-DQCfqVjw.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, d as ContractSchema } from './index-D3H572Cz.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';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as viem from 'viem';
2
2
  import { Account, Address, Hex } from 'viem';
3
3
  import { G as GenLayerChain } from './chains-D6DgvIVA.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, d as ContractSchema } from './index-DDgbU3hK.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, d as ContractSchema } from './index-BpBLcwxn.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';
package/dist/index.js CHANGED
@@ -530,10 +530,10 @@ function extractGenCallResult(result) {
530
530
  }
531
531
  var contractActions = (client, publicClient) => {
532
532
  return {
533
- /** Retrieves the source code of a deployed contract. Localnet only. */
533
+ /** Retrieves the source code of a deployed contract. Studio only. */
534
534
  getContractCode: async (address) => {
535
- if (client.chain.id !== localnet.id) {
536
- throw new Error(`getContractCode is only available on localnet (current chain: ${client.chain.name})`);
535
+ if (!client.chain.isStudio) {
536
+ throw new Error(`getContractCode is only available on Studio networks (current chain: ${client.chain.name})`);
537
537
  }
538
538
  const result = await client.request({
539
539
  method: "gen_getContractCode",
@@ -542,10 +542,10 @@ var contractActions = (client, publicClient) => {
542
542
  const codeBytes = b64ToArray(result);
543
543
  return new TextDecoder().decode(codeBytes);
544
544
  },
545
- /** Gets the schema (methods and constructor) of a deployed contract. Localnet only. */
545
+ /** Gets the schema (methods and constructor) of a deployed contract. Studio only. */
546
546
  getContractSchema: async (address) => {
547
- if (client.chain.id !== localnet.id) {
548
- throw new Error(`getContractSchema is only available on localnet (current chain: ${client.chain.name})`);
547
+ if (!client.chain.isStudio) {
548
+ throw new Error(`getContractSchema is only available on Studio networks (current chain: ${client.chain.name})`);
549
549
  }
550
550
  const schema = await client.request({
551
551
  method: "gen_getContractSchema",
@@ -553,10 +553,10 @@ var contractActions = (client, publicClient) => {
553
553
  });
554
554
  return schema;
555
555
  },
556
- /** Generates a schema for contract code without deploying it. Localnet only. */
556
+ /** Generates a schema for contract code without deploying it. Studio only. */
557
557
  getContractSchemaForCode: async (contractCode) => {
558
- if (client.chain.id !== localnet.id) {
559
- throw new Error(`getContractSchema is only available on localnet (current chain: ${client.chain.name})`);
558
+ if (!client.chain.isStudio) {
559
+ throw new Error(`getContractSchemaForCode is only available on Studio networks (current chain: ${client.chain.name})`);
560
560
  }
561
561
  const schema = await client.request({
562
562
  method: "gen_getContractSchemaForCode",
@@ -792,61 +792,52 @@ var contractActions = (client, publicClient) => {
792
792
  }
793
793
  const senderAccount = account || client.account;
794
794
  const encodedData = _encodeSubmitAppealData({ client, txId });
795
- const validatedAccount = validateAccount(senderAccount);
796
- if (!client.chain.consensusMainContract?.address) {
797
- throw new Error("Consensus main contract not initialized.");
798
- }
799
- const nonce = await client.getCurrentNonce({ address: validatedAccount.address });
800
- let estimatedGas;
801
- try {
802
- estimatedGas = await client.estimateTransactionGas({
803
- to: client.chain.consensusMainContract.address,
804
- data: encodedData,
805
- value,
806
- nonce
807
- });
808
- } catch (err) {
809
- console.error("Gas estimation failed, using default 200_000:", err);
810
- estimatedGas = 200000n;
811
- }
812
- const gasPriceHex = await client.request({ method: "eth_gasPrice" });
813
- const txRequest = {
814
- account: validatedAccount,
815
- to: client.chain.consensusMainContract.address,
816
- data: encodedData,
795
+ await _sendConsensusCall({
796
+ client,
797
+ publicClient,
798
+ encodedData,
799
+ senderAccount,
817
800
  value,
818
- gas: estimatedGas,
819
- gasPrice: BigInt(gasPriceHex),
820
- nonce,
821
- chainId: client.chain.id
822
- };
823
- if (validatedAccount.type === "local") {
824
- if (!validatedAccount.signTransaction) {
825
- throw new Error("Local account does not support signTransaction.");
826
- }
827
- const serializedTransaction = await validatedAccount.signTransaction(txRequest);
828
- const evmHash = await client.sendRawTransaction({ serializedTransaction });
829
- const receipt = await publicClient.waitForTransactionReceipt({ hash: evmHash });
830
- if (receipt.status === "reverted") {
831
- throw new Error(`Appeal reverted: EVM tx ${evmHash}`);
832
- }
833
- } else {
834
- const evmHash = await client.request({
835
- method: "eth_sendTransaction",
836
- params: [{
837
- from: validatedAccount.address,
838
- to: client.chain.consensusMainContract.address,
839
- data: encodedData,
840
- value: value ? `0x${value.toString(16)}` : void 0,
841
- gas: `0x${estimatedGas.toString(16)}`
842
- }]
843
- });
844
- const receipt = await publicClient.waitForTransactionReceipt({ hash: evmHash });
845
- if (receipt.status === "reverted") {
846
- throw new Error(`Appeal reverted: EVM tx ${evmHash}`);
847
- }
848
- }
801
+ operationName: "Appeal"
802
+ });
849
803
  return txId;
804
+ },
805
+ /** Finalizes a single GenLayer transaction that is ready to be finalized. Returns the EVM transaction hash. */
806
+ finalizeTransaction: async (args) => {
807
+ const { account, txId } = args;
808
+ const senderAccount = account || client.account;
809
+ const encodedData = encodeFunctionData({
810
+ abi: client.chain.consensusMainContract?.abi,
811
+ functionName: "finalizeTransaction",
812
+ args: [txId]
813
+ });
814
+ return _sendConsensusCall({
815
+ client,
816
+ publicClient,
817
+ encodedData,
818
+ senderAccount,
819
+ operationName: "Finalize"
820
+ });
821
+ },
822
+ /** Batch-finalizes idle GenLayer transactions (those stuck without progressing). Returns the EVM transaction hash. */
823
+ finalizeIdlenessTxs: async (args) => {
824
+ const { account, txIds } = args;
825
+ if (txIds.length === 0) {
826
+ throw new Error("finalizeIdlenessTxs requires at least one txId.");
827
+ }
828
+ const senderAccount = account || client.account;
829
+ const encodedData = encodeFunctionData({
830
+ abi: client.chain.consensusMainContract?.abi,
831
+ functionName: "finalizeIdlenessTxs",
832
+ args: [txIds]
833
+ });
834
+ return _sendConsensusCall({
835
+ client,
836
+ publicClient,
837
+ encodedData,
838
+ senderAccount,
839
+ operationName: "Finalize idleness"
840
+ });
850
841
  }
851
842
  };
852
843
  };
@@ -959,6 +950,69 @@ var _encodeSubmitAppealData = ({
959
950
  args: [txId]
960
951
  });
961
952
  };
953
+ var _sendConsensusCall = async ({
954
+ client,
955
+ publicClient,
956
+ encodedData,
957
+ senderAccount,
958
+ value = 0n,
959
+ operationName = "Consensus call"
960
+ }) => {
961
+ if (!client.chain.consensusMainContract?.address) {
962
+ throw new Error("Consensus main contract not initialized.");
963
+ }
964
+ const validatedAccount = validateAccount(senderAccount);
965
+ const nonce = await client.getCurrentNonce({ address: validatedAccount.address });
966
+ let estimatedGas;
967
+ try {
968
+ estimatedGas = await client.estimateTransactionGas({
969
+ to: client.chain.consensusMainContract.address,
970
+ data: encodedData,
971
+ value
972
+ });
973
+ } catch (err) {
974
+ console.error("Gas estimation failed, using default 200_000:", err);
975
+ estimatedGas = 200000n;
976
+ }
977
+ const gasPriceHex = await client.request({ method: "eth_gasPrice" });
978
+ if (validatedAccount.type === "local") {
979
+ if (!validatedAccount.signTransaction) {
980
+ throw new Error("Local account does not support signTransaction.");
981
+ }
982
+ const txRequest = {
983
+ account: validatedAccount,
984
+ to: client.chain.consensusMainContract.address,
985
+ data: encodedData,
986
+ value,
987
+ gas: estimatedGas,
988
+ gasPrice: BigInt(gasPriceHex),
989
+ nonce,
990
+ chainId: client.chain.id
991
+ };
992
+ const serializedTransaction = await validatedAccount.signTransaction(txRequest);
993
+ const evmHash2 = await client.sendRawTransaction({ serializedTransaction });
994
+ const receipt2 = await publicClient.waitForTransactionReceipt({ hash: evmHash2 });
995
+ if (receipt2.status === "reverted") {
996
+ throw new Error(`${operationName} reverted: EVM tx ${evmHash2}`);
997
+ }
998
+ return evmHash2;
999
+ }
1000
+ const evmHash = await client.request({
1001
+ method: "eth_sendTransaction",
1002
+ params: [{
1003
+ from: validatedAccount.address,
1004
+ to: client.chain.consensusMainContract.address,
1005
+ data: encodedData,
1006
+ value: value ? `0x${value.toString(16)}` : void 0,
1007
+ gas: `0x${estimatedGas.toString(16)}`
1008
+ }]
1009
+ });
1010
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: evmHash });
1011
+ if (receipt.status === "reverted") {
1012
+ throw new Error(`${operationName} reverted: EVM tx ${evmHash}`);
1013
+ }
1014
+ return evmHash;
1015
+ };
962
1016
  var isAddTransactionAbiMismatchError = (error) => {
963
1017
  const seen = /* @__PURE__ */ new WeakSet();
964
1018
  const serializedError = typeof error === "object" && error !== null ? JSON.stringify(error, (_key, value) => {
@@ -1088,6 +1142,9 @@ var _sendTransaction = async ({
1088
1142
  method: "eth_sendTransaction",
1089
1143
  params: [formattedRequest]
1090
1144
  });
1145
+ if (client.chain.isStudio) {
1146
+ return evmTxHash;
1147
+ }
1091
1148
  const externalReceipt = await publicClient.waitForTransactionReceipt({ hash: evmTxHash });
1092
1149
  if (externalReceipt.status === "reverted") {
1093
1150
  throw new Error(`Transaction reverted: EVM tx ${evmTxHash} to consensus contract ${client.chain.consensusMainContract?.address} was reverted.`);
@@ -1384,7 +1441,7 @@ var receiptActions = (client, publicClient) => ({
1384
1441
  const requestedStatus = transactionsStatusNameToNumber[status];
1385
1442
  if (transactionStatusString === requestedStatus || status === "ACCEPTED" /* ACCEPTED */ && isDecidedState(transactionStatusString)) {
1386
1443
  let finalTransaction = transaction;
1387
- if (client.chain.id === localnet.id) {
1444
+ if (client.chain.isStudio) {
1388
1445
  finalTransaction = decodeLocalnetTransaction(transaction);
1389
1446
  }
1390
1447
  if (!fullTransaction) {
@@ -2264,6 +2321,7 @@ var PROVIDER_METHODS = /* @__PURE__ */ new Set([
2264
2321
  "eth_signTypedData_v4"
2265
2322
  ]);
2266
2323
  var assertChainMatch = async (provider, chainConfig) => {
2324
+ if (chainConfig.isStudio) return;
2267
2325
  const expectedChainIdHex = `0x${chainConfig.id.toString(16)}`;
2268
2326
  try {
2269
2327
  const currentChainId = await provider.request({ method: "eth_chainId" });
@@ -1,3 +1,3 @@
1
1
  export { Account, Address } from 'viem';
2
- export { O as BannedValidatorInfo, e as CalldataAddress, C as CalldataEncodable, j as ContractMethod, i as ContractMethodBase, g as ContractParamsArraySchemaElement, h as ContractParamsSchema, d as ContractSchema, o as DECIDED_STATES, z as DebugTraceResult, a as DecodedCallData, D as DecodedDeployData, a7 as DelegatorClaimOptions, a6 as DelegatorExitOptions, a5 as DelegatorJoinOptions, Z as DelegatorJoinResult, R as EpochData, U as EpochInfo, E as ExecutionResult, G as GenLayerClient, f as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, L as LeaderReceipt, M as MethodDescription, N as Network, P as PendingDeposit, K as PendingWithdrawal, a4 as SetIdentityOptions, a3 as SetOperatorOptions, A as SnapSource, Q as StakeInfo, a8 as StakingActions, B as StakingContract, X as StakingTransactionResult, k as TransactionHash, y as TransactionHashVariant, m as TransactionResult, r as TransactionResultNameToNumber, l as TransactionStatus, x as TransactionType, a1 as ValidatorClaimOptions, $ as ValidatorDepositOptions, a0 as ValidatorExitOptions, I as ValidatorIdentity, J as ValidatorInfo, _ as ValidatorJoinOptions, Y as ValidatorJoinResult, a2 as ValidatorPrimeOptions, F as ValidatorView, u as VoteType, W as WithdrawalCommit, s as executionResultNumberToName, p as isDecidedState, q as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, w as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-DQCfqVjw.cjs';
2
+ export { O as BannedValidatorInfo, e as CalldataAddress, C as CalldataEncodable, j as ContractMethod, i as ContractMethodBase, g as ContractParamsArraySchemaElement, h as ContractParamsSchema, d as ContractSchema, o as DECIDED_STATES, z as DebugTraceResult, a as DecodedCallData, D as DecodedDeployData, a7 as DelegatorClaimOptions, a6 as DelegatorExitOptions, a5 as DelegatorJoinOptions, Z as DelegatorJoinResult, R as EpochData, U as EpochInfo, E as ExecutionResult, G as GenLayerClient, f as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, L as LeaderReceipt, M as MethodDescription, N as Network, P as PendingDeposit, K as PendingWithdrawal, a4 as SetIdentityOptions, a3 as SetOperatorOptions, A as SnapSource, Q as StakeInfo, a8 as StakingActions, B as StakingContract, X as StakingTransactionResult, k as TransactionHash, y as TransactionHashVariant, m as TransactionResult, r as TransactionResultNameToNumber, l as TransactionStatus, x as TransactionType, a1 as ValidatorClaimOptions, $ as ValidatorDepositOptions, a0 as ValidatorExitOptions, I as ValidatorIdentity, J as ValidatorInfo, _ as ValidatorJoinOptions, Y as ValidatorJoinResult, a2 as ValidatorPrimeOptions, F as ValidatorView, u as VoteType, W as WithdrawalCommit, s as executionResultNumberToName, p as isDecidedState, q as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, w as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-D3H572Cz.cjs';
3
3
  export { G as GenLayerChain } from '../chains-D6DgvIVA.cjs';
@@ -1,3 +1,3 @@
1
1
  export { Account, Address } from 'viem';
2
- export { O as BannedValidatorInfo, e as CalldataAddress, C as CalldataEncodable, j as ContractMethod, i as ContractMethodBase, g as ContractParamsArraySchemaElement, h as ContractParamsSchema, d as ContractSchema, o as DECIDED_STATES, z as DebugTraceResult, a as DecodedCallData, D as DecodedDeployData, a7 as DelegatorClaimOptions, a6 as DelegatorExitOptions, a5 as DelegatorJoinOptions, Z as DelegatorJoinResult, R as EpochData, U as EpochInfo, E as ExecutionResult, G as GenLayerClient, f as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, L as LeaderReceipt, M as MethodDescription, N as Network, P as PendingDeposit, K as PendingWithdrawal, a4 as SetIdentityOptions, a3 as SetOperatorOptions, A as SnapSource, Q as StakeInfo, a8 as StakingActions, B as StakingContract, X as StakingTransactionResult, k as TransactionHash, y as TransactionHashVariant, m as TransactionResult, r as TransactionResultNameToNumber, l as TransactionStatus, x as TransactionType, a1 as ValidatorClaimOptions, $ as ValidatorDepositOptions, a0 as ValidatorExitOptions, I as ValidatorIdentity, J as ValidatorInfo, _ as ValidatorJoinOptions, Y as ValidatorJoinResult, a2 as ValidatorPrimeOptions, F as ValidatorView, u as VoteType, W as WithdrawalCommit, s as executionResultNumberToName, p as isDecidedState, q as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, w as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-DDgbU3hK.js';
2
+ export { O as BannedValidatorInfo, e as CalldataAddress, C as CalldataEncodable, j as ContractMethod, i as ContractMethodBase, g as ContractParamsArraySchemaElement, h as ContractParamsSchema, d as ContractSchema, o as DECIDED_STATES, z as DebugTraceResult, a as DecodedCallData, D as DecodedDeployData, a7 as DelegatorClaimOptions, a6 as DelegatorExitOptions, a5 as DelegatorJoinOptions, Z as DelegatorJoinResult, R as EpochData, U as EpochInfo, E as ExecutionResult, G as GenLayerClient, f as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, L as LeaderReceipt, M as MethodDescription, N as Network, P as PendingDeposit, K as PendingWithdrawal, a4 as SetIdentityOptions, a3 as SetOperatorOptions, A as SnapSource, Q as StakeInfo, a8 as StakingActions, B as StakingContract, X as StakingTransactionResult, k as TransactionHash, y as TransactionHashVariant, m as TransactionResult, r as TransactionResultNameToNumber, l as TransactionStatus, x as TransactionType, a1 as ValidatorClaimOptions, $ as ValidatorDepositOptions, a0 as ValidatorExitOptions, I as ValidatorIdentity, J as ValidatorInfo, _ as ValidatorJoinOptions, Y as ValidatorJoinResult, a2 as ValidatorPrimeOptions, F as ValidatorView, u as VoteType, W as WithdrawalCommit, s as executionResultNumberToName, p as isDecidedState, q as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, w as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-BpBLcwxn.js';
3
3
  export { G as GenLayerChain } from '../chains-D6DgvIVA.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "genlayer-js",
3
3
  "type": "module",
4
- "version": "0.28.2",
4
+ "version": "0.28.5",
5
5
  "description": "GenLayer JavaScript SDK",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",