genlayer-js 0.19.0 → 0.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.cjs +198 -103
  2. package/dist/index.js +181 -86
  3. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -624,10 +624,11 @@ var contractActions = (client, publicClient) => {
624
624
  leaderOnly = false,
625
625
  consensusMaxRotations = client.chain.defaultConsensusMaxRotations
626
626
  } = args;
627
+ await client.initializeConsensusSmartContract();
627
628
  const data = [encode(makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
628
629
  const serializedData = serialize(data);
629
630
  const senderAccount = account || client.account;
630
- const encodedData = _encodeAddTransactionData({
631
+ const { primaryEncodedData, fallbackEncodedData } = _encodeAddTransactionData({
631
632
  client,
632
633
  senderAccount,
633
634
  recipient: address,
@@ -637,7 +638,8 @@ var contractActions = (client, publicClient) => {
637
638
  return _sendTransaction({
638
639
  client,
639
640
  publicClient,
640
- encodedData,
641
+ encodedData: primaryEncodedData,
642
+ fallbackEncodedData,
641
643
  senderAccount,
642
644
  value
643
645
  });
@@ -651,6 +653,7 @@ var contractActions = (client, publicClient) => {
651
653
  leaderOnly = false,
652
654
  consensusMaxRotations = client.chain.defaultConsensusMaxRotations
653
655
  } = args;
656
+ await client.initializeConsensusSmartContract();
654
657
  const data = [
655
658
  code,
656
659
  encode(makeCalldataObject(void 0, constructorArgs, kwargs)),
@@ -658,7 +661,7 @@ var contractActions = (client, publicClient) => {
658
661
  ];
659
662
  const serializedData = serialize(data);
660
663
  const senderAccount = account || client.account;
661
- const encodedData = _encodeAddTransactionData({
664
+ const { primaryEncodedData, fallbackEncodedData } = _encodeAddTransactionData({
662
665
  client,
663
666
  senderAccount,
664
667
  recipient: _viem.zeroAddress,
@@ -668,7 +671,8 @@ var contractActions = (client, publicClient) => {
668
671
  return _sendTransaction({
669
672
  client,
670
673
  publicClient,
671
- encodedData,
674
+ encodedData: primaryEncodedData,
675
+ fallbackEncodedData,
672
676
  senderAccount
673
677
  });
674
678
  },
@@ -693,6 +697,50 @@ var validateAccount = (Account4) => {
693
697
  }
694
698
  return Account4;
695
699
  };
700
+ var ADD_TRANSACTION_ABI_V5 = [
701
+ {
702
+ type: "function",
703
+ name: "addTransaction",
704
+ stateMutability: "nonpayable",
705
+ inputs: [
706
+ { name: "_sender", type: "address" },
707
+ { name: "_recipient", type: "address" },
708
+ { name: "_numOfInitialValidators", type: "uint256" },
709
+ { name: "_maxRotations", type: "uint256" },
710
+ { name: "_txData", type: "bytes" }
711
+ ],
712
+ outputs: []
713
+ }
714
+ ];
715
+ var ADD_TRANSACTION_ABI_V6 = [
716
+ {
717
+ type: "function",
718
+ name: "addTransaction",
719
+ stateMutability: "nonpayable",
720
+ inputs: [
721
+ { name: "_sender", type: "address" },
722
+ { name: "_recipient", type: "address" },
723
+ { name: "_numOfInitialValidators", type: "uint256" },
724
+ { name: "_maxRotations", type: "uint256" },
725
+ { name: "_txData", type: "bytes" },
726
+ { name: "_validUntil", type: "uint256" }
727
+ ],
728
+ outputs: []
729
+ }
730
+ ];
731
+ var getAddTransactionInputCount = (abi) => {
732
+ if (!abi || !Array.isArray(abi)) {
733
+ return 0;
734
+ }
735
+ const addTransactionFunction = abi.find((item) => {
736
+ if (!item || typeof item !== "object") {
737
+ return false;
738
+ }
739
+ const candidate = item;
740
+ return candidate.type === "function" && candidate.name === "addTransaction";
741
+ });
742
+ return Array.isArray(_optionalChain([addTransactionFunction, 'optionalAccess', _11 => _11.inputs])) ? addTransactionFunction.inputs.length : 0;
743
+ };
696
744
  var _encodeAddTransactionData = ({
697
745
  client,
698
746
  senderAccount,
@@ -701,106 +749,139 @@ var _encodeAddTransactionData = ({
701
749
  consensusMaxRotations = client.chain.defaultConsensusMaxRotations
702
750
  }) => {
703
751
  const validatedSenderAccount = validateAccount(senderAccount);
704
- return _viem.encodeFunctionData.call(void 0, {
705
- abi: _optionalChain([client, 'access', _11 => _11.chain, 'access', _12 => _12.consensusMainContract, 'optionalAccess', _13 => _13.abi]),
752
+ const addTransactionArgs = [
753
+ validatedSenderAccount.address,
754
+ recipient,
755
+ client.chain.defaultNumberOfInitialValidators,
756
+ consensusMaxRotations,
757
+ data
758
+ ];
759
+ const encodedDataV5 = _viem.encodeFunctionData.call(void 0, {
760
+ abi: ADD_TRANSACTION_ABI_V5,
706
761
  functionName: "addTransaction",
707
- args: [
708
- validatedSenderAccount.address,
709
- recipient,
710
- client.chain.defaultNumberOfInitialValidators,
711
- consensusMaxRotations,
712
- data
713
- ]
762
+ args: addTransactionArgs
714
763
  });
764
+ const encodedDataV6 = _viem.encodeFunctionData.call(void 0, {
765
+ abi: ADD_TRANSACTION_ABI_V6,
766
+ functionName: "addTransaction",
767
+ args: [...addTransactionArgs, 0n]
768
+ });
769
+ if (getAddTransactionInputCount(_optionalChain([client, 'access', _12 => _12.chain, 'access', _13 => _13.consensusMainContract, 'optionalAccess', _14 => _14.abi])) >= 6) {
770
+ return {
771
+ primaryEncodedData: encodedDataV6,
772
+ fallbackEncodedData: encodedDataV5
773
+ };
774
+ }
775
+ return {
776
+ primaryEncodedData: encodedDataV5,
777
+ fallbackEncodedData: encodedDataV6
778
+ };
715
779
  };
716
780
  var _encodeSubmitAppealData = ({
717
781
  client,
718
782
  txId
719
783
  }) => {
720
784
  return _viem.encodeFunctionData.call(void 0, {
721
- abi: _optionalChain([client, 'access', _14 => _14.chain, 'access', _15 => _15.consensusMainContract, 'optionalAccess', _16 => _16.abi]),
785
+ abi: _optionalChain([client, 'access', _15 => _15.chain, 'access', _16 => _16.consensusMainContract, 'optionalAccess', _17 => _17.abi]),
722
786
  functionName: "submitAppeal",
723
787
  args: [txId]
724
788
  });
725
789
  };
790
+ var isAddTransactionAbiMismatchError = (error) => {
791
+ const errorMessage = String(
792
+ _optionalChain([error, 'optionalAccess', _18 => _18.shortMessage]) || _optionalChain([error, 'optionalAccess', _19 => _19.details]) || _optionalChain([error, 'optionalAccess', _20 => _20.message]) || error || ""
793
+ ).toLowerCase();
794
+ return errorMessage.includes("invalid pointer in tuple") || errorMessage.includes("could not decode") || errorMessage.includes("invalid arrayify value") || errorMessage.includes("types/value length mismatch");
795
+ };
726
796
  var _sendTransaction = async ({
727
797
  client,
728
798
  publicClient,
729
799
  encodedData,
800
+ fallbackEncodedData,
730
801
  senderAccount,
731
802
  value = 0n
732
803
  }) => {
733
- if (!_optionalChain([client, 'access', _17 => _17.chain, 'access', _18 => _18.consensusMainContract, 'optionalAccess', _19 => _19.address])) {
804
+ if (!_optionalChain([client, 'access', _21 => _21.chain, 'access', _22 => _22.consensusMainContract, 'optionalAccess', _23 => _23.address])) {
734
805
  throw new Error("Consensus main contract not initialized. Please ensure client is properly initialized.");
735
806
  }
736
807
  const validatedSenderAccount = validateAccount(senderAccount);
737
808
  const nonce = await client.getCurrentNonce({ address: validatedSenderAccount.address });
738
- let estimatedGas;
739
- try {
740
- estimatedGas = await client.estimateTransactionGas({
741
- from: validatedSenderAccount.address,
742
- to: _optionalChain([client, 'access', _20 => _20.chain, 'access', _21 => _21.consensusMainContract, 'optionalAccess', _22 => _22.address]),
743
- data: encodedData,
744
- value
745
- });
746
- } catch (err) {
747
- console.error("Gas estimation failed, using default 200_000:", err);
748
- estimatedGas = 200000n;
749
- }
750
- if (_optionalChain([validatedSenderAccount, 'optionalAccess', _23 => _23.type]) === "local") {
751
- if (!_optionalChain([validatedSenderAccount, 'optionalAccess', _24 => _24.signTransaction])) {
752
- throw new Error("Account does not support signTransaction");
809
+ const sendWithEncodedData = async (encodedDataForSend) => {
810
+ let estimatedGas;
811
+ try {
812
+ estimatedGas = await client.estimateTransactionGas({
813
+ from: validatedSenderAccount.address,
814
+ to: _optionalChain([client, 'access', _24 => _24.chain, 'access', _25 => _25.consensusMainContract, 'optionalAccess', _26 => _26.address]),
815
+ data: encodedDataForSend,
816
+ value
817
+ });
818
+ } catch (err) {
819
+ console.error("Gas estimation failed, using default 200_000:", err);
820
+ estimatedGas = 200000n;
753
821
  }
754
- const gasPriceHex = await client.request({
755
- method: "eth_gasPrice"
756
- });
757
- const transactionRequest2 = {
822
+ if (_optionalChain([validatedSenderAccount, 'optionalAccess', _27 => _27.type]) === "local") {
823
+ if (!_optionalChain([validatedSenderAccount, 'optionalAccess', _28 => _28.signTransaction])) {
824
+ throw new Error("Account does not support signTransaction");
825
+ }
826
+ const gasPriceHex = await client.request({
827
+ method: "eth_gasPrice"
828
+ });
829
+ const transactionRequest2 = {
830
+ account: validatedSenderAccount,
831
+ to: _optionalChain([client, 'access', _29 => _29.chain, 'access', _30 => _30.consensusMainContract, 'optionalAccess', _31 => _31.address]),
832
+ data: encodedDataForSend,
833
+ type: "legacy",
834
+ nonce: Number(nonce),
835
+ value,
836
+ gas: estimatedGas,
837
+ gasPrice: BigInt(gasPriceHex),
838
+ chainId: client.chain.id
839
+ };
840
+ const serializedTransaction = await validatedSenderAccount.signTransaction(transactionRequest2);
841
+ const txHash = await client.sendRawTransaction({ serializedTransaction });
842
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
843
+ if (receipt.status === "reverted") {
844
+ throw new Error("Transaction reverted");
845
+ }
846
+ const newTxEvents = _viem.parseEventLogs.call(void 0, {
847
+ abi: _optionalChain([client, 'access', _32 => _32.chain, 'access', _33 => _33.consensusMainContract, 'optionalAccess', _34 => _34.abi]),
848
+ eventName: "NewTransaction",
849
+ logs: receipt.logs
850
+ });
851
+ if (newTxEvents.length === 0) {
852
+ throw new Error("Transaction not processed by consensus");
853
+ }
854
+ return newTxEvents[0].args["txId"];
855
+ }
856
+ const transactionRequest = await client.prepareTransactionRequest({
758
857
  account: validatedSenderAccount,
759
- to: _optionalChain([client, 'access', _25 => _25.chain, 'access', _26 => _26.consensusMainContract, 'optionalAccess', _27 => _27.address]),
760
- data: encodedData,
858
+ to: _optionalChain([client, 'access', _35 => _35.chain, 'access', _36 => _36.consensusMainContract, 'optionalAccess', _37 => _37.address]),
859
+ data: encodedDataForSend,
761
860
  type: "legacy",
762
861
  nonce: Number(nonce),
763
862
  value,
764
- gas: estimatedGas,
765
- gasPrice: BigInt(gasPriceHex),
766
- chainId: client.chain.id
863
+ gas: estimatedGas
864
+ });
865
+ const formattedRequest = {
866
+ from: transactionRequest.from,
867
+ to: transactionRequest.to,
868
+ data: encodedDataForSend,
869
+ value: transactionRequest.value ? `0x${transactionRequest.value.toString(16)}` : "0x0",
870
+ gas: transactionRequest.gas ? `0x${transactionRequest.gas.toString(16)}` : "0x5208"
767
871
  };
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 = _viem.parseEventLogs.call(void 0, {
775
- abi: _optionalChain([client, 'access', _28 => _28.chain, 'access', _29 => _29.consensusMainContract, 'optionalAccess', _30 => _30.abi]),
776
- eventName: "NewTransaction",
777
- logs: receipt.logs
872
+ return await client.request({
873
+ method: "eth_sendTransaction",
874
+ params: [formattedRequest]
778
875
  });
779
- if (newTxEvents.length === 0) {
780
- throw new Error("Transaction not processed by consensus");
876
+ };
877
+ try {
878
+ return await sendWithEncodedData(encodedData);
879
+ } catch (error) {
880
+ if (!fallbackEncodedData || !isAddTransactionAbiMismatchError(error)) {
881
+ throw error;
781
882
  }
782
- return newTxEvents[0].args["txId"];
883
+ return await sendWithEncodedData(fallbackEncodedData);
783
884
  }
784
- const transactionRequest = await client.prepareTransactionRequest({
785
- account: validatedSenderAccount,
786
- to: _optionalChain([client, 'access', _31 => _31.chain, 'access', _32 => _32.consensusMainContract, 'optionalAccess', _33 => _33.address]),
787
- data: encodedData,
788
- type: "legacy",
789
- nonce: Number(nonce),
790
- value,
791
- gas: estimatedGas
792
- });
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]
803
- });
804
885
  };
805
886
 
806
887
  // src/config/transactions.ts
@@ -1007,7 +1088,7 @@ var simplifyTransactionReceipt = (tx) => {
1007
1088
  var decodeLocalnetTransaction = (tx) => {
1008
1089
  if (!tx.data) return tx;
1009
1090
  try {
1010
- const leaderReceipt = _optionalChain([tx, 'access', _34 => _34.consensus_data, 'optionalAccess', _35 => _35.leader_receipt]);
1091
+ const leaderReceipt = _optionalChain([tx, 'access', _38 => _38.consensus_data, 'optionalAccess', _39 => _39.leader_receipt]);
1011
1092
  if (leaderReceipt) {
1012
1093
  const receipts = Array.isArray(leaderReceipt) ? leaderReceipt : [leaderReceipt];
1013
1094
  receipts.forEach((receipt) => {
@@ -1038,7 +1119,7 @@ var decodeLocalnetTransaction = (tx) => {
1038
1119
  }
1039
1120
  });
1040
1121
  }
1041
- if (_optionalChain([tx, 'access', _36 => _36.data, 'optionalAccess', _37 => _37.calldata]) && typeof tx.data.calldata === "string") {
1122
+ if (_optionalChain([tx, 'access', _40 => _40.data, 'optionalAccess', _41 => _41.calldata]) && typeof tx.data.calldata === "string") {
1042
1123
  tx.data.calldata = {
1043
1124
  base64: tx.data.calldata,
1044
1125
  ...calldataToUserFriendlyJson(b64ToArray(tx.data.calldata))
@@ -1100,8 +1181,8 @@ var transactionActions = (client, publicClient) => ({
1100
1181
  return decodeLocalnetTransaction(transaction2);
1101
1182
  }
1102
1183
  const transaction = await publicClient.readContract({
1103
- address: _optionalChain([client, 'access', _38 => _38.chain, 'access', _39 => _39.consensusDataContract, 'optionalAccess', _40 => _40.address]),
1104
- abi: _optionalChain([client, 'access', _41 => _41.chain, 'access', _42 => _42.consensusDataContract, 'optionalAccess', _43 => _43.abi]),
1184
+ address: _optionalChain([client, 'access', _42 => _42.chain, 'access', _43 => _43.consensusDataContract, 'optionalAccess', _44 => _44.address]),
1185
+ abi: _optionalChain([client, 'access', _45 => _45.chain, 'access', _46 => _46.consensusDataContract, 'optionalAccess', _47 => _47.abi]),
1105
1186
  functionName: "getTransactionData",
1106
1187
  args: [
1107
1188
  hash,
@@ -1113,7 +1194,7 @@ var transactionActions = (client, publicClient) => ({
1113
1194
  },
1114
1195
  estimateTransactionGas: async (transactionParams) => {
1115
1196
  const formattedParams = {
1116
- from: transactionParams.from || _optionalChain([client, 'access', _44 => _44.account, 'optionalAccess', _45 => _45.address]),
1197
+ from: transactionParams.from || _optionalChain([client, 'access', _48 => _48.account, 'optionalAccess', _49 => _49.address]),
1117
1198
  to: transactionParams.to,
1118
1199
  data: transactionParams.data || "0x",
1119
1200
  value: transactionParams.value ? `0x${transactionParams.value.toString(16)}` : "0x0"
@@ -1155,7 +1236,7 @@ var connect = async (client, network = "studionet", snapSource = "npm") => {
1155
1236
  chainName: selectedNetwork.name,
1156
1237
  rpcUrls: selectedNetwork.rpcUrls.default.http,
1157
1238
  nativeCurrency: selectedNetwork.nativeCurrency,
1158
- blockExplorerUrls: [_optionalChain([selectedNetwork, 'access', _46 => _46.blockExplorers, 'optionalAccess', _47 => _47.default, 'access', _48 => _48.url])]
1239
+ blockExplorerUrls: [_optionalChain([selectedNetwork, 'access', _50 => _50.blockExplorers, 'optionalAccess', _51 => _51.default, 'access', _52 => _52.url])]
1159
1240
  };
1160
1241
  const currentChainId = await window.ethereum.request({ method: "eth_chainId" });
1161
1242
  if (currentChainId !== chainIdHex) {
@@ -1189,10 +1270,10 @@ var metamaskClient = async (snapSource = "npm") => {
1189
1270
  }
1190
1271
  const isFlask = async () => {
1191
1272
  try {
1192
- const clientVersion = await _optionalChain([window, 'access', _49 => _49.ethereum, 'optionalAccess', _50 => _50.request, 'call', _51 => _51({
1273
+ const clientVersion = await _optionalChain([window, 'access', _53 => _53.ethereum, 'optionalAccess', _54 => _54.request, 'call', _55 => _55({
1193
1274
  method: "web3_clientVersion"
1194
1275
  })]);
1195
- return _optionalChain([clientVersion, 'optionalAccess', _52 => _52.includes, 'call', _53 => _53("flask")]);
1276
+ return _optionalChain([clientVersion, 'optionalAccess', _56 => _56.includes, 'call', _57 => _57("flask")]);
1196
1277
  } catch (error) {
1197
1278
  console.error("Error detecting Flask:", error);
1198
1279
  return false;
@@ -1200,7 +1281,7 @@ var metamaskClient = async (snapSource = "npm") => {
1200
1281
  };
1201
1282
  const installedSnaps = async () => {
1202
1283
  try {
1203
- return await _optionalChain([window, 'access', _54 => _54.ethereum, 'optionalAccess', _55 => _55.request, 'call', _56 => _56({
1284
+ return await _optionalChain([window, 'access', _58 => _58.ethereum, 'optionalAccess', _59 => _59.request, 'call', _60 => _60({
1204
1285
  method: "wallet_getSnaps"
1205
1286
  })]);
1206
1287
  } catch (error) {
@@ -1287,7 +1368,7 @@ function extractRevertReason(err) {
1287
1368
  }
1288
1369
  const revertError = err.walk((e) => e instanceof _viem.ContractFunctionRevertedError);
1289
1370
  if (revertError instanceof _viem.ContractFunctionRevertedError) {
1290
- if (_optionalChain([revertError, 'access', _57 => _57.data, 'optionalAccess', _58 => _58.errorName])) {
1371
+ if (_optionalChain([revertError, 'access', _61 => _61.data, 'optionalAccess', _62 => _62.errorName])) {
1291
1372
  return revertError.data.errorName;
1292
1373
  }
1293
1374
  return revertError.reason || "Unknown reason";
@@ -1375,7 +1456,7 @@ var stakingActions = (client, publicClient) => {
1375
1456
  };
1376
1457
  const getStakingAddress = () => {
1377
1458
  const stakingConfig = client.chain.stakingContract;
1378
- if (!_optionalChain([stakingConfig, 'optionalAccess', _59 => _59.address]) || stakingConfig.address === "0x0000000000000000000000000000000000000000") {
1459
+ if (!_optionalChain([stakingConfig, 'optionalAccess', _63 => _63.address]) || stakingConfig.address === "0x0000000000000000000000000000000000000000") {
1379
1460
  throw new Error("Staking is not supported on studio-based networks. Use testnet-asimov for staking operations.");
1380
1461
  }
1381
1462
  return stakingConfig.address;
@@ -1456,10 +1537,10 @@ var stakingActions = (client, publicClient) => {
1456
1537
  return executeWrite({ to: getStakingAddress(), data });
1457
1538
  },
1458
1539
  validatorClaim: async (options) => {
1459
- if (!_optionalChain([options, 'optionalAccess', _60 => _60.validator]) && !client.account) {
1540
+ if (!_optionalChain([options, 'optionalAccess', _64 => _64.validator]) && !client.account) {
1460
1541
  throw new Error("Either provide validator address or initialize client with an account");
1461
1542
  }
1462
- const validatorAddress = _optionalChain([options, 'optionalAccess', _61 => _61.validator]) || client.account.address;
1543
+ const validatorAddress = _optionalChain([options, 'optionalAccess', _65 => _65.validator]) || client.account.address;
1463
1544
  const data = _viem.encodeFunctionData.call(void 0, {
1464
1545
  abi: _chunk5TKVNHAOcjs.STAKING_ABI,
1465
1546
  functionName: "validatorClaim",
@@ -1800,29 +1881,43 @@ var stakingActions = (client, publicClient) => {
1800
1881
  function chainActions(client) {
1801
1882
  return {
1802
1883
  initializeConsensusSmartContract: async (forceReset = false) => {
1803
- if (_optionalChain([client, 'access', _62 => _62.chain, 'optionalAccess', _63 => _63.id]) === _chunk5TKVNHAOcjs.testnetAsimov.id) {
1884
+ if (_optionalChain([client, 'access', _66 => _66.chain, 'optionalAccess', _67 => _67.id]) === _chunk5TKVNHAOcjs.testnetAsimov.id) {
1804
1885
  return;
1805
1886
  }
1806
- if (!forceReset && _optionalChain([client, 'access', _64 => _64.chain, 'access', _65 => _65.consensusMainContract, 'optionalAccess', _66 => _66.address]) && _optionalChain([client, 'access', _67 => _67.chain, 'access', _68 => _68.consensusMainContract, 'optionalAccess', _69 => _69.abi])) {
1887
+ const hasStaticConsensusContract = !!_optionalChain([client, 'access', _68 => _68.chain, 'access', _69 => _69.consensusMainContract, 'optionalAccess', _70 => _70.address]) && !!_optionalChain([client, 'access', _71 => _71.chain, 'access', _72 => _72.consensusMainContract, 'optionalAccess', _73 => _73.abi]);
1888
+ const isLocalOrStudioChain = _optionalChain([client, 'access', _74 => _74.chain, 'optionalAccess', _75 => _75.id]) === _chunk5TKVNHAOcjs.localnet.id || _optionalChain([client, 'access', _76 => _76.chain, 'optionalAccess', _77 => _77.id]) === _chunk5TKVNHAOcjs.studionet.id;
1889
+ if (!forceReset && hasStaticConsensusContract && !isLocalOrStudioChain) {
1807
1890
  return;
1808
1891
  }
1809
- const contractsResponse = await fetch(client.chain.rpcUrls.default.http[0], {
1810
- method: "POST",
1811
- headers: {
1812
- "Content-Type": "application/json"
1813
- },
1814
- body: JSON.stringify({
1815
- jsonrpc: "2.0",
1816
- id: Date.now(),
1817
- method: "sim_getConsensusContract",
1818
- params: ["ConsensusMain"]
1819
- })
1820
- });
1821
- if (!contractsResponse.ok) {
1822
- throw new Error("Failed to fetch ConsensusMain contract");
1892
+ try {
1893
+ const contractsResponse = await fetch(client.chain.rpcUrls.default.http[0], {
1894
+ method: "POST",
1895
+ headers: {
1896
+ "Content-Type": "application/json"
1897
+ },
1898
+ body: JSON.stringify({
1899
+ jsonrpc: "2.0",
1900
+ id: Date.now(),
1901
+ method: "sim_getConsensusContract",
1902
+ params: ["ConsensusMain"]
1903
+ })
1904
+ });
1905
+ if (!contractsResponse.ok) {
1906
+ throw new Error("Failed to fetch ConsensusMain contract");
1907
+ }
1908
+ const consensusMainContract = await contractsResponse.json();
1909
+ if (_optionalChain([consensusMainContract, 'optionalAccess', _78 => _78.error]) || !_optionalChain([consensusMainContract, 'optionalAccess', _79 => _79.result, 'optionalAccess', _80 => _80.address]) || !_optionalChain([consensusMainContract, 'optionalAccess', _81 => _81.result, 'optionalAccess', _82 => _82.abi])) {
1910
+ throw new Error("ConsensusMain response did not include a valid contract");
1911
+ }
1912
+ client.chain.consensusMainContract = consensusMainContract.result;
1913
+ client.chain.__consensusAbiFetchedFromRpc = true;
1914
+ } catch (error) {
1915
+ if (hasStaticConsensusContract) {
1916
+ client.chain.__consensusAbiFetchedFromRpc = false;
1917
+ return;
1918
+ }
1919
+ throw error;
1823
1920
  }
1824
- const consensusMainContract = await contractsResponse.json();
1825
- client.chain.consensusMainContract = consensusMainContract.result;
1826
1921
  }
1827
1922
  };
1828
1923
  }
package/dist/index.js CHANGED
@@ -624,10 +624,11 @@ var contractActions = (client, publicClient) => {
624
624
  leaderOnly = false,
625
625
  consensusMaxRotations = client.chain.defaultConsensusMaxRotations
626
626
  } = args;
627
+ await client.initializeConsensusSmartContract();
627
628
  const data = [encode(makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
628
629
  const serializedData = serialize(data);
629
630
  const senderAccount = account || client.account;
630
- const encodedData = _encodeAddTransactionData({
631
+ const { primaryEncodedData, fallbackEncodedData } = _encodeAddTransactionData({
631
632
  client,
632
633
  senderAccount,
633
634
  recipient: address,
@@ -637,7 +638,8 @@ var contractActions = (client, publicClient) => {
637
638
  return _sendTransaction({
638
639
  client,
639
640
  publicClient,
640
- encodedData,
641
+ encodedData: primaryEncodedData,
642
+ fallbackEncodedData,
641
643
  senderAccount,
642
644
  value
643
645
  });
@@ -651,6 +653,7 @@ var contractActions = (client, publicClient) => {
651
653
  leaderOnly = false,
652
654
  consensusMaxRotations = client.chain.defaultConsensusMaxRotations
653
655
  } = args;
656
+ await client.initializeConsensusSmartContract();
654
657
  const data = [
655
658
  code,
656
659
  encode(makeCalldataObject(void 0, constructorArgs, kwargs)),
@@ -658,7 +661,7 @@ var contractActions = (client, publicClient) => {
658
661
  ];
659
662
  const serializedData = serialize(data);
660
663
  const senderAccount = account || client.account;
661
- const encodedData = _encodeAddTransactionData({
664
+ const { primaryEncodedData, fallbackEncodedData } = _encodeAddTransactionData({
662
665
  client,
663
666
  senderAccount,
664
667
  recipient: zeroAddress,
@@ -668,7 +671,8 @@ var contractActions = (client, publicClient) => {
668
671
  return _sendTransaction({
669
672
  client,
670
673
  publicClient,
671
- encodedData,
674
+ encodedData: primaryEncodedData,
675
+ fallbackEncodedData,
672
676
  senderAccount
673
677
  });
674
678
  },
@@ -693,6 +697,50 @@ var validateAccount = (Account4) => {
693
697
  }
694
698
  return Account4;
695
699
  };
700
+ var ADD_TRANSACTION_ABI_V5 = [
701
+ {
702
+ type: "function",
703
+ name: "addTransaction",
704
+ stateMutability: "nonpayable",
705
+ inputs: [
706
+ { name: "_sender", type: "address" },
707
+ { name: "_recipient", type: "address" },
708
+ { name: "_numOfInitialValidators", type: "uint256" },
709
+ { name: "_maxRotations", type: "uint256" },
710
+ { name: "_txData", type: "bytes" }
711
+ ],
712
+ outputs: []
713
+ }
714
+ ];
715
+ var ADD_TRANSACTION_ABI_V6 = [
716
+ {
717
+ type: "function",
718
+ name: "addTransaction",
719
+ stateMutability: "nonpayable",
720
+ inputs: [
721
+ { name: "_sender", type: "address" },
722
+ { name: "_recipient", type: "address" },
723
+ { name: "_numOfInitialValidators", type: "uint256" },
724
+ { name: "_maxRotations", type: "uint256" },
725
+ { name: "_txData", type: "bytes" },
726
+ { name: "_validUntil", type: "uint256" }
727
+ ],
728
+ outputs: []
729
+ }
730
+ ];
731
+ var getAddTransactionInputCount = (abi) => {
732
+ if (!abi || !Array.isArray(abi)) {
733
+ return 0;
734
+ }
735
+ const addTransactionFunction = abi.find((item) => {
736
+ if (!item || typeof item !== "object") {
737
+ return false;
738
+ }
739
+ const candidate = item;
740
+ return candidate.type === "function" && candidate.name === "addTransaction";
741
+ });
742
+ return Array.isArray(addTransactionFunction?.inputs) ? addTransactionFunction.inputs.length : 0;
743
+ };
696
744
  var _encodeAddTransactionData = ({
697
745
  client,
698
746
  senderAccount,
@@ -701,17 +749,33 @@ var _encodeAddTransactionData = ({
701
749
  consensusMaxRotations = client.chain.defaultConsensusMaxRotations
702
750
  }) => {
703
751
  const validatedSenderAccount = validateAccount(senderAccount);
704
- return encodeFunctionData({
705
- abi: client.chain.consensusMainContract?.abi,
752
+ const addTransactionArgs = [
753
+ validatedSenderAccount.address,
754
+ recipient,
755
+ client.chain.defaultNumberOfInitialValidators,
756
+ consensusMaxRotations,
757
+ data
758
+ ];
759
+ const encodedDataV5 = encodeFunctionData({
760
+ abi: ADD_TRANSACTION_ABI_V5,
706
761
  functionName: "addTransaction",
707
- args: [
708
- validatedSenderAccount.address,
709
- recipient,
710
- client.chain.defaultNumberOfInitialValidators,
711
- consensusMaxRotations,
712
- data
713
- ]
762
+ args: addTransactionArgs
763
+ });
764
+ const encodedDataV6 = encodeFunctionData({
765
+ abi: ADD_TRANSACTION_ABI_V6,
766
+ functionName: "addTransaction",
767
+ args: [...addTransactionArgs, 0n]
714
768
  });
769
+ if (getAddTransactionInputCount(client.chain.consensusMainContract?.abi) >= 6) {
770
+ return {
771
+ primaryEncodedData: encodedDataV6,
772
+ fallbackEncodedData: encodedDataV5
773
+ };
774
+ }
775
+ return {
776
+ primaryEncodedData: encodedDataV5,
777
+ fallbackEncodedData: encodedDataV6
778
+ };
715
779
  };
716
780
  var _encodeSubmitAppealData = ({
717
781
  client,
@@ -723,10 +787,17 @@ var _encodeSubmitAppealData = ({
723
787
  args: [txId]
724
788
  });
725
789
  };
790
+ var isAddTransactionAbiMismatchError = (error) => {
791
+ const errorMessage = String(
792
+ error?.shortMessage || error?.details || error?.message || error || ""
793
+ ).toLowerCase();
794
+ return errorMessage.includes("invalid pointer in tuple") || errorMessage.includes("could not decode") || errorMessage.includes("invalid arrayify value") || errorMessage.includes("types/value length mismatch");
795
+ };
726
796
  var _sendTransaction = async ({
727
797
  client,
728
798
  publicClient,
729
799
  encodedData,
800
+ fallbackEncodedData,
730
801
  senderAccount,
731
802
  value = 0n
732
803
  }) => {
@@ -735,72 +806,82 @@ var _sendTransaction = async ({
735
806
  }
736
807
  const validatedSenderAccount = validateAccount(senderAccount);
737
808
  const nonce = await client.getCurrentNonce({ address: validatedSenderAccount.address });
738
- let estimatedGas;
739
- try {
740
- estimatedGas = await client.estimateTransactionGas({
741
- from: validatedSenderAccount.address,
742
- to: client.chain.consensusMainContract?.address,
743
- data: encodedData,
744
- value
745
- });
746
- } catch (err) {
747
- console.error("Gas estimation failed, using default 200_000:", err);
748
- estimatedGas = 200000n;
749
- }
750
- if (validatedSenderAccount?.type === "local") {
751
- if (!validatedSenderAccount?.signTransaction) {
752
- throw new Error("Account does not support signTransaction");
809
+ const sendWithEncodedData = async (encodedDataForSend) => {
810
+ let estimatedGas;
811
+ try {
812
+ estimatedGas = await client.estimateTransactionGas({
813
+ from: validatedSenderAccount.address,
814
+ to: client.chain.consensusMainContract?.address,
815
+ data: encodedDataForSend,
816
+ value
817
+ });
818
+ } catch (err) {
819
+ console.error("Gas estimation failed, using default 200_000:", err);
820
+ estimatedGas = 200000n;
753
821
  }
754
- const gasPriceHex = await client.request({
755
- method: "eth_gasPrice"
756
- });
757
- const transactionRequest2 = {
822
+ if (validatedSenderAccount?.type === "local") {
823
+ if (!validatedSenderAccount?.signTransaction) {
824
+ throw new Error("Account does not support signTransaction");
825
+ }
826
+ const gasPriceHex = await client.request({
827
+ method: "eth_gasPrice"
828
+ });
829
+ const transactionRequest2 = {
830
+ account: validatedSenderAccount,
831
+ to: client.chain.consensusMainContract?.address,
832
+ data: encodedDataForSend,
833
+ type: "legacy",
834
+ nonce: Number(nonce),
835
+ value,
836
+ gas: estimatedGas,
837
+ gasPrice: BigInt(gasPriceHex),
838
+ chainId: client.chain.id
839
+ };
840
+ const serializedTransaction = await validatedSenderAccount.signTransaction(transactionRequest2);
841
+ const txHash = await client.sendRawTransaction({ serializedTransaction });
842
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
843
+ if (receipt.status === "reverted") {
844
+ throw new Error("Transaction reverted");
845
+ }
846
+ const newTxEvents = parseEventLogs({
847
+ abi: client.chain.consensusMainContract?.abi,
848
+ eventName: "NewTransaction",
849
+ logs: receipt.logs
850
+ });
851
+ if (newTxEvents.length === 0) {
852
+ throw new Error("Transaction not processed by consensus");
853
+ }
854
+ return newTxEvents[0].args["txId"];
855
+ }
856
+ const transactionRequest = await client.prepareTransactionRequest({
758
857
  account: validatedSenderAccount,
759
858
  to: client.chain.consensusMainContract?.address,
760
- data: encodedData,
859
+ data: encodedDataForSend,
761
860
  type: "legacy",
762
861
  nonce: Number(nonce),
763
862
  value,
764
- gas: estimatedGas,
765
- gasPrice: BigInt(gasPriceHex),
766
- chainId: client.chain.id
863
+ gas: estimatedGas
864
+ });
865
+ const formattedRequest = {
866
+ from: transactionRequest.from,
867
+ to: transactionRequest.to,
868
+ data: encodedDataForSend,
869
+ value: transactionRequest.value ? `0x${transactionRequest.value.toString(16)}` : "0x0",
870
+ gas: transactionRequest.gas ? `0x${transactionRequest.gas.toString(16)}` : "0x5208"
767
871
  };
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
872
+ return await client.request({
873
+ method: "eth_sendTransaction",
874
+ params: [formattedRequest]
778
875
  });
779
- if (newTxEvents.length === 0) {
780
- throw new Error("Transaction not processed by consensus");
876
+ };
877
+ try {
878
+ return await sendWithEncodedData(encodedData);
879
+ } catch (error) {
880
+ if (!fallbackEncodedData || !isAddTransactionAbiMismatchError(error)) {
881
+ throw error;
781
882
  }
782
- return newTxEvents[0].args["txId"];
883
+ return await sendWithEncodedData(fallbackEncodedData);
783
884
  }
784
- const transactionRequest = await client.prepareTransactionRequest({
785
- account: validatedSenderAccount,
786
- to: client.chain.consensusMainContract?.address,
787
- data: encodedData,
788
- type: "legacy",
789
- nonce: Number(nonce),
790
- value,
791
- gas: estimatedGas
792
- });
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]
803
- });
804
885
  };
805
886
 
806
887
  // src/config/transactions.ts
@@ -1803,26 +1884,40 @@ function chainActions(client) {
1803
1884
  if (client.chain?.id === testnetAsimov.id) {
1804
1885
  return;
1805
1886
  }
1806
- if (!forceReset && client.chain.consensusMainContract?.address && client.chain.consensusMainContract?.abi) {
1887
+ const hasStaticConsensusContract = !!client.chain.consensusMainContract?.address && !!client.chain.consensusMainContract?.abi;
1888
+ const isLocalOrStudioChain = client.chain?.id === localnet.id || client.chain?.id === studionet.id;
1889
+ if (!forceReset && hasStaticConsensusContract && !isLocalOrStudioChain) {
1807
1890
  return;
1808
1891
  }
1809
- const contractsResponse = await fetch(client.chain.rpcUrls.default.http[0], {
1810
- method: "POST",
1811
- headers: {
1812
- "Content-Type": "application/json"
1813
- },
1814
- body: JSON.stringify({
1815
- jsonrpc: "2.0",
1816
- id: Date.now(),
1817
- method: "sim_getConsensusContract",
1818
- params: ["ConsensusMain"]
1819
- })
1820
- });
1821
- if (!contractsResponse.ok) {
1822
- throw new Error("Failed to fetch ConsensusMain contract");
1892
+ try {
1893
+ const contractsResponse = await fetch(client.chain.rpcUrls.default.http[0], {
1894
+ method: "POST",
1895
+ headers: {
1896
+ "Content-Type": "application/json"
1897
+ },
1898
+ body: JSON.stringify({
1899
+ jsonrpc: "2.0",
1900
+ id: Date.now(),
1901
+ method: "sim_getConsensusContract",
1902
+ params: ["ConsensusMain"]
1903
+ })
1904
+ });
1905
+ if (!contractsResponse.ok) {
1906
+ throw new Error("Failed to fetch ConsensusMain contract");
1907
+ }
1908
+ const consensusMainContract = await contractsResponse.json();
1909
+ if (consensusMainContract?.error || !consensusMainContract?.result?.address || !consensusMainContract?.result?.abi) {
1910
+ throw new Error("ConsensusMain response did not include a valid contract");
1911
+ }
1912
+ client.chain.consensusMainContract = consensusMainContract.result;
1913
+ client.chain.__consensusAbiFetchedFromRpc = true;
1914
+ } catch (error) {
1915
+ if (hasStaticConsensusContract) {
1916
+ client.chain.__consensusAbiFetchedFromRpc = false;
1917
+ return;
1918
+ }
1919
+ throw error;
1823
1920
  }
1824
- const consensusMainContract = await contractsResponse.json();
1825
- client.chain.consensusMainContract = consensusMainContract.result;
1826
1921
  }
1827
1922
  };
1828
1923
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "genlayer-js",
3
3
  "type": "module",
4
- "version": "0.19.0",
4
+ "version": "0.19.2",
5
5
  "description": "GenLayer JavaScript SDK",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",