genlayer-js 0.18.0 → 0.18.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
 
2
2
 
3
+ ## 0.18.2 (2025-09-18)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **transactions:** handle all DECIDED states in waitForTransactionReceipt ([#116](https://github.com/genlayerlabs/genlayer-js/issues/116)) ([78433d7](https://github.com/genlayerlabs/genlayer-js/commit/78433d7224298ab418ca16a87de497149b66b5f7))
9
+
10
+ ## 0.18.1 (2025-09-11)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * replace hardcoded gas 21000 ([#115](https://github.com/genlayerlabs/genlayer-js/issues/115)) ([8eacd5d](https://github.com/genlayerlabs/genlayer-js/commit/8eacd5dbba9ae85f0232ec525076582ea8b6b045))
16
+
3
17
  ## 0.18.0 (2025-09-04)
4
18
 
5
19
 
@@ -75,6 +75,19 @@ var transactionsStatusNameToNumber = {
75
75
  ["VALIDATORS_TIMEOUT" /* VALIDATORS_TIMEOUT */]: "12",
76
76
  ["LEADER_TIMEOUT" /* LEADER_TIMEOUT */]: "13"
77
77
  };
78
+ var DECIDED_STATES = [
79
+ "ACCEPTED" /* ACCEPTED */,
80
+ "UNDETERMINED" /* UNDETERMINED */,
81
+ "LEADER_TIMEOUT" /* LEADER_TIMEOUT */,
82
+ "VALIDATORS_TIMEOUT" /* VALIDATORS_TIMEOUT */,
83
+ "CANCELED" /* CANCELED */,
84
+ "FINALIZED" /* FINALIZED */
85
+ ];
86
+ function isDecidedState(status) {
87
+ return DECIDED_STATES.some(
88
+ (state) => transactionsStatusNameToNumber[state] === status
89
+ );
90
+ }
78
91
  var transactionResultNumberToName = {
79
92
  "0": "IDLE" /* IDLE */,
80
93
  "1": "AGREE" /* AGREE */,
@@ -129,6 +142,8 @@ export {
129
142
  TransactionResult,
130
143
  transactionsStatusNumberToName,
131
144
  transactionsStatusNameToNumber,
145
+ DECIDED_STATES,
146
+ isDecidedState,
132
147
  transactionResultNumberToName,
133
148
  TransactionResultNameToNumber,
134
149
  VoteType,
@@ -75,6 +75,19 @@ var transactionsStatusNameToNumber = {
75
75
  ["VALIDATORS_TIMEOUT" /* VALIDATORS_TIMEOUT */]: "12",
76
76
  ["LEADER_TIMEOUT" /* LEADER_TIMEOUT */]: "13"
77
77
  };
78
+ var DECIDED_STATES = [
79
+ "ACCEPTED" /* ACCEPTED */,
80
+ "UNDETERMINED" /* UNDETERMINED */,
81
+ "LEADER_TIMEOUT" /* LEADER_TIMEOUT */,
82
+ "VALIDATORS_TIMEOUT" /* VALIDATORS_TIMEOUT */,
83
+ "CANCELED" /* CANCELED */,
84
+ "FINALIZED" /* FINALIZED */
85
+ ];
86
+ function isDecidedState(status) {
87
+ return DECIDED_STATES.some(
88
+ (state) => transactionsStatusNameToNumber[state] === status
89
+ );
90
+ }
78
91
  var transactionResultNumberToName = {
79
92
  "0": "IDLE" /* IDLE */,
80
93
  "1": "AGREE" /* AGREE */,
@@ -135,4 +148,6 @@ var TransactionHashVariant = /* @__PURE__ */ ((TransactionHashVariant2) => {
135
148
 
136
149
 
137
150
 
138
- exports.CalldataAddress = CalldataAddress; exports.TransactionStatus = TransactionStatus; exports.TransactionResult = TransactionResult; exports.transactionsStatusNumberToName = transactionsStatusNumberToName; exports.transactionsStatusNameToNumber = transactionsStatusNameToNumber; exports.transactionResultNumberToName = transactionResultNumberToName; exports.TransactionResultNameToNumber = TransactionResultNameToNumber; exports.VoteType = VoteType; exports.voteTypeNumberToName = voteTypeNumberToName; exports.voteTypeNameToNumber = voteTypeNameToNumber; exports.TransactionHashVariant = TransactionHashVariant;
151
+
152
+
153
+ exports.CalldataAddress = CalldataAddress; exports.TransactionStatus = TransactionStatus; exports.TransactionResult = TransactionResult; exports.transactionsStatusNumberToName = transactionsStatusNumberToName; exports.transactionsStatusNameToNumber = transactionsStatusNameToNumber; exports.DECIDED_STATES = DECIDED_STATES; exports.isDecidedState = isDecidedState; exports.transactionResultNumberToName = transactionResultNumberToName; exports.TransactionResultNameToNumber = TransactionResultNameToNumber; exports.VoteType = VoteType; exports.voteTypeNumberToName = voteTypeNumberToName; exports.voteTypeNameToNumber = voteTypeNameToNumber; exports.TransactionHashVariant = TransactionHashVariant;
@@ -80,6 +80,8 @@ declare const transactionsStatusNameToNumber: {
80
80
  VALIDATORS_TIMEOUT: string;
81
81
  LEADER_TIMEOUT: string;
82
82
  };
83
+ declare const DECIDED_STATES: TransactionStatus[];
84
+ declare function isDecidedState(status: string): boolean;
83
85
  declare const transactionResultNumberToName: {
84
86
  "0": TransactionResult;
85
87
  "1": TransactionResult;
@@ -313,6 +315,9 @@ type GenLayerMethod = {
313
315
  } | {
314
316
  method: "eth_getTransactionCount";
315
317
  params: [address: Address, block: string];
318
+ } | {
319
+ method: "eth_estimateGas";
320
+ params: [transactionParams: any];
316
321
  } | {
317
322
  method: "gen_call";
318
323
  params: [requestParams: any];
@@ -375,6 +380,12 @@ type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<Client<Transpor
375
380
  getCurrentNonce: (args: {
376
381
  address: Address;
377
382
  }) => Promise<number>;
383
+ estimateTransactionGas: (transactionParams: {
384
+ from?: Address;
385
+ to: Address;
386
+ data?: `0x${string}`;
387
+ value?: bigint;
388
+ }) => Promise<bigint>;
378
389
  waitForTransactionReceipt: (args: {
379
390
  hash: TransactionHash;
380
391
  status?: TransactionStatus;
@@ -393,4 +404,4 @@ type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<Client<Transpor
393
404
  }) => Promise<any>;
394
405
  };
395
406
 
396
- export { type CalldataEncodable as C, type DecodedDeployData as D, type GenLayerClient as G, type Hash as H, type MethodDescription as M, type Network as N, type SnapSource as S, type TransactionDataElement as T, VoteType as V, type DecodedCallData as a, type GenLayerRawTransaction as b, type GenLayerTransaction as c, CalldataAddress as d, type GenLayerMethod as e, type ContractParamsArraySchemaElement as f, type ContractParamsSchema as g, type ContractMethodBase as h, type ContractMethod as i, type ContractSchema as j, type TransactionHash as k, TransactionStatus as l, TransactionResult as m, transactionsStatusNameToNumber as n, transactionResultNumberToName as o, TransactionResultNameToNumber as p, voteTypeNameToNumber as q, type TransactionType as r, TransactionHashVariant as s, transactionsStatusNumberToName as t, voteTypeNumberToName as v };
407
+ export { type CalldataEncodable as C, type DecodedDeployData as D, type GenLayerClient as G, type Hash as H, type MethodDescription as M, type Network as N, type SnapSource as S, type TransactionDataElement as T, VoteType as V, type DecodedCallData as a, type GenLayerRawTransaction as b, type GenLayerTransaction as c, CalldataAddress as d, type GenLayerMethod as e, type ContractParamsArraySchemaElement as f, type ContractParamsSchema as g, type ContractMethodBase as h, type ContractMethod as i, type ContractSchema as j, type TransactionHash as k, TransactionStatus as l, TransactionResult as m, transactionsStatusNameToNumber as n, DECIDED_STATES as o, isDecidedState as p, transactionResultNumberToName as q, TransactionResultNameToNumber as r, voteTypeNameToNumber as s, transactionsStatusNumberToName as t, type TransactionType as u, voteTypeNumberToName as v, TransactionHashVariant as w };
@@ -80,6 +80,8 @@ declare const transactionsStatusNameToNumber: {
80
80
  VALIDATORS_TIMEOUT: string;
81
81
  LEADER_TIMEOUT: string;
82
82
  };
83
+ declare const DECIDED_STATES: TransactionStatus[];
84
+ declare function isDecidedState(status: string): boolean;
83
85
  declare const transactionResultNumberToName: {
84
86
  "0": TransactionResult;
85
87
  "1": TransactionResult;
@@ -313,6 +315,9 @@ type GenLayerMethod = {
313
315
  } | {
314
316
  method: "eth_getTransactionCount";
315
317
  params: [address: Address, block: string];
318
+ } | {
319
+ method: "eth_estimateGas";
320
+ params: [transactionParams: any];
316
321
  } | {
317
322
  method: "gen_call";
318
323
  params: [requestParams: any];
@@ -375,6 +380,12 @@ type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<Client<Transpor
375
380
  getCurrentNonce: (args: {
376
381
  address: Address;
377
382
  }) => Promise<number>;
383
+ estimateTransactionGas: (transactionParams: {
384
+ from?: Address;
385
+ to: Address;
386
+ data?: `0x${string}`;
387
+ value?: bigint;
388
+ }) => Promise<bigint>;
378
389
  waitForTransactionReceipt: (args: {
379
390
  hash: TransactionHash;
380
391
  status?: TransactionStatus;
@@ -393,4 +404,4 @@ type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<Client<Transpor
393
404
  }) => Promise<any>;
394
405
  };
395
406
 
396
- export { type CalldataEncodable as C, type DecodedDeployData as D, type GenLayerClient as G, type Hash as H, type MethodDescription as M, type Network as N, type SnapSource as S, type TransactionDataElement as T, VoteType as V, type DecodedCallData as a, type GenLayerRawTransaction as b, type GenLayerTransaction as c, CalldataAddress as d, type GenLayerMethod as e, type ContractParamsArraySchemaElement as f, type ContractParamsSchema as g, type ContractMethodBase as h, type ContractMethod as i, type ContractSchema as j, type TransactionHash as k, TransactionStatus as l, TransactionResult as m, transactionsStatusNameToNumber as n, transactionResultNumberToName as o, TransactionResultNameToNumber as p, voteTypeNameToNumber as q, type TransactionType as r, TransactionHashVariant as s, transactionsStatusNumberToName as t, voteTypeNumberToName as v };
407
+ export { type CalldataEncodable as C, type DecodedDeployData as D, type GenLayerClient as G, type Hash as H, type MethodDescription as M, type Network as N, type SnapSource as S, type TransactionDataElement as T, VoteType as V, type DecodedCallData as a, type GenLayerRawTransaction as b, type GenLayerTransaction as c, CalldataAddress as d, type GenLayerMethod as e, type ContractParamsArraySchemaElement as f, type ContractParamsSchema as g, type ContractMethodBase as h, type ContractMethod as i, type ContractSchema as j, type TransactionHash as k, TransactionStatus as l, TransactionResult as m, transactionsStatusNameToNumber as n, DECIDED_STATES as o, isDecidedState as p, transactionResultNumberToName as q, TransactionResultNameToNumber as r, voteTypeNameToNumber as s, transactionsStatusNumberToName as t, type TransactionType as u, voteTypeNumberToName as v, TransactionHashVariant as w };
package/dist/index.cjs CHANGED
@@ -10,7 +10,8 @@ var _chunkZKBMABRAcjs = require('./chunk-ZKBMABRA.cjs');
10
10
 
11
11
 
12
12
 
13
- var _chunkH4ZYXVV2cjs = require('./chunk-H4ZYXVV2.cjs');
13
+
14
+ var _chunkFPZNF3JHcjs = require('./chunk-FPZNF3JH.cjs');
14
15
 
15
16
 
16
17
  var _chunk75ZPJI57cjs = require('./chunk-75ZPJI57.cjs');
@@ -183,7 +184,7 @@ function encodeImpl(to, data) {
183
184
  }
184
185
  } else if (data instanceof Map) {
185
186
  encodeMap(to, data);
186
- } else if (data instanceof _chunkH4ZYXVV2cjs.CalldataAddress) {
187
+ } else if (data instanceof _chunkFPZNF3JHcjs.CalldataAddress) {
187
188
  to.push(SPECIAL_ADDR);
188
189
  for (const c of data.bytes) {
189
190
  to.push(c);
@@ -258,7 +259,7 @@ function decodeImpl(data, index) {
258
259
  case BigInt(SPECIAL_ADDR): {
259
260
  const res = data.slice(index.i, index.i + 20);
260
261
  index.i += 20;
261
- return new (0, _chunkH4ZYXVV2cjs.CalldataAddress)(res);
262
+ return new (0, _chunkFPZNF3JHcjs.CalldataAddress)(res);
262
263
  }
263
264
  }
264
265
  const type = Number(cur & 0xffn) & (1 << BITS_IN_TYPE) - 1;
@@ -370,7 +371,7 @@ function toStringImpl(data, to) {
370
371
  to.push("]");
371
372
  } else if (data instanceof Map) {
372
373
  toStringImplMap(data.entries(), to);
373
- } else if (data instanceof _chunkH4ZYXVV2cjs.CalldataAddress) {
374
+ } else if (data instanceof _chunkFPZNF3JHcjs.CalldataAddress) {
374
375
  to.push("addr#");
375
376
  for (const c of data.bytes) {
376
377
  to.push(c.toString(16));
@@ -493,7 +494,7 @@ function _toJsonSafeDeep(value, seen) {
493
494
  }
494
495
  return obj;
495
496
  }
496
- if (value instanceof _chunkH4ZYXVV2cjs.CalldataAddress) {
497
+ if (value instanceof _chunkFPZNF3JHcjs.CalldataAddress) {
497
498
  return _viem.toHex.call(void 0, value.bytes);
498
499
  }
499
500
  if (Object.getPrototypeOf(value) === Object.prototype) {
@@ -730,16 +731,28 @@ var _sendTransaction = async ({
730
731
  }
731
732
  const validatedSenderAccount = validateAccount(senderAccount);
732
733
  const nonce = await client.getCurrentNonce({ address: validatedSenderAccount.address });
734
+ let estimatedGas;
735
+ try {
736
+ estimatedGas = await client.estimateTransactionGas({
737
+ from: validatedSenderAccount.address,
738
+ to: _optionalChain([client, 'access', _20 => _20.chain, 'access', _21 => _21.consensusMainContract, 'optionalAccess', _22 => _22.address]),
739
+ data: encodedData,
740
+ value
741
+ });
742
+ } catch (error) {
743
+ console.warn("Gas estimation failed, using fallback value:", error);
744
+ estimatedGas = 200000n;
745
+ }
733
746
  const transactionRequest = await client.prepareTransactionRequest({
734
747
  account: validatedSenderAccount,
735
- to: _optionalChain([client, 'access', _20 => _20.chain, 'access', _21 => _21.consensusMainContract, 'optionalAccess', _22 => _22.address]),
748
+ to: _optionalChain([client, 'access', _23 => _23.chain, 'access', _24 => _24.consensusMainContract, 'optionalAccess', _25 => _25.address]),
736
749
  data: encodedData,
737
750
  type: "legacy",
738
751
  nonce: Number(nonce),
739
752
  value,
740
- gas: 21000n
753
+ gas: estimatedGas
741
754
  });
742
- if (_optionalChain([validatedSenderAccount, 'optionalAccess', _23 => _23.type]) !== "local") {
755
+ if (_optionalChain([validatedSenderAccount, 'optionalAccess', _26 => _26.type]) !== "local") {
743
756
  const formattedRequest = {
744
757
  from: transactionRequest.from,
745
758
  to: transactionRequest.to,
@@ -752,7 +765,7 @@ var _sendTransaction = async ({
752
765
  params: [formattedRequest]
753
766
  });
754
767
  }
755
- if (!_optionalChain([validatedSenderAccount, 'optionalAccess', _24 => _24.signTransaction])) {
768
+ if (!_optionalChain([validatedSenderAccount, 'optionalAccess', _27 => _27.signTransaction])) {
756
769
  throw new Error("Account does not support signTransaction");
757
770
  }
758
771
  const serializedTransaction = await validatedSenderAccount.signTransaction(transactionRequest);
@@ -762,7 +775,7 @@ var _sendTransaction = async ({
762
775
  throw new Error("Transaction reverted");
763
776
  }
764
777
  const newTxEvents = _viem.parseEventLogs.call(void 0, {
765
- abi: _optionalChain([client, 'access', _25 => _25.chain, 'access', _26 => _26.consensusMainContract, 'optionalAccess', _27 => _27.abi]),
778
+ abi: _optionalChain([client, 'access', _28 => _28.chain, 'access', _29 => _29.consensusMainContract, 'optionalAccess', _30 => _30.abi]),
766
779
  eventName: "NewTransaction",
767
780
  logs: receipt.logs
768
781
  });
@@ -884,8 +897,8 @@ var decodeTransaction = (tx) => {
884
897
  processingBlock: tx.readStateBlockRange.processingBlock.toString(),
885
898
  proposalBlock: tx.readStateBlockRange.proposalBlock.toString()
886
899
  },
887
- statusName: _chunkH4ZYXVV2cjs.transactionsStatusNumberToName[String(tx.status)],
888
- resultName: _chunkH4ZYXVV2cjs.transactionResultNumberToName[String(tx.result)],
900
+ statusName: _chunkFPZNF3JHcjs.transactionsStatusNumberToName[String(tx.status)],
901
+ resultName: _chunkFPZNF3JHcjs.transactionResultNumberToName[String(tx.result)],
889
902
  lastRound: {
890
903
  ...tx.lastRound,
891
904
  round: tx.lastRound.round.toString(),
@@ -895,7 +908,7 @@ var decodeTransaction = (tx) => {
895
908
  appealBond: tx.lastRound.appealBond.toString(),
896
909
  rotationsLeft: tx.lastRound.rotationsLeft.toString(),
897
910
  validatorVotesName: tx.lastRound.validatorVotes.map(
898
- (vote) => _chunkH4ZYXVV2cjs.voteTypeNumberToName[String(vote)]
911
+ (vote) => _chunkFPZNF3JHcjs.voteTypeNumberToName[String(vote)]
899
912
  )
900
913
  }
901
914
  };
@@ -975,7 +988,7 @@ var simplifyTransactionReceipt = (tx) => {
975
988
  var decodeLocalnetTransaction = (tx) => {
976
989
  if (!tx.data) return tx;
977
990
  try {
978
- const leaderReceipt = _optionalChain([tx, 'access', _28 => _28.consensus_data, 'optionalAccess', _29 => _29.leader_receipt]);
991
+ const leaderReceipt = _optionalChain([tx, 'access', _31 => _31.consensus_data, 'optionalAccess', _32 => _32.leader_receipt]);
979
992
  if (leaderReceipt) {
980
993
  const receipts = Array.isArray(leaderReceipt) ? leaderReceipt : [leaderReceipt];
981
994
  receipts.forEach((receipt) => {
@@ -1006,7 +1019,7 @@ var decodeLocalnetTransaction = (tx) => {
1006
1019
  }
1007
1020
  });
1008
1021
  }
1009
- if (_optionalChain([tx, 'access', _30 => _30.data, 'optionalAccess', _31 => _31.calldata]) && typeof tx.data.calldata === "string") {
1022
+ if (_optionalChain([tx, 'access', _33 => _33.data, 'optionalAccess', _34 => _34.calldata]) && typeof tx.data.calldata === "string") {
1010
1023
  tx.data.calldata = {
1011
1024
  base64: tx.data.calldata,
1012
1025
  ...calldataToUserFriendlyJson(b64ToArray(tx.data.calldata))
@@ -1034,9 +1047,8 @@ var receiptActions = (client, publicClient) => ({
1034
1047
  throw new Error("Transaction not found");
1035
1048
  }
1036
1049
  const transactionStatusString = String(transaction.status);
1037
- const transactionStatusFinalized = _chunkH4ZYXVV2cjs.transactionsStatusNameToNumber["FINALIZED" /* FINALIZED */];
1038
- const requestedStatus = _chunkH4ZYXVV2cjs.transactionsStatusNameToNumber[status];
1039
- if (transactionStatusString === requestedStatus || status === "ACCEPTED" /* ACCEPTED */ && transactionStatusString === transactionStatusFinalized) {
1050
+ const requestedStatus = _chunkFPZNF3JHcjs.transactionsStatusNameToNumber[status];
1051
+ if (transactionStatusString === requestedStatus || status === "ACCEPTED" /* ACCEPTED */ && _chunkFPZNF3JHcjs.isDecidedState.call(void 0, transactionStatusString)) {
1040
1052
  let finalTransaction = transaction;
1041
1053
  if (client.chain.id === _chunkZKBMABRAcjs.localnet.id) {
1042
1054
  finalTransaction = decodeLocalnetTransaction(transaction);
@@ -1064,13 +1076,13 @@ var transactionActions = (client, publicClient) => ({
1064
1076
  if (client.chain.id === _chunkZKBMABRAcjs.localnet.id) {
1065
1077
  const transaction2 = await client.getTransaction({ hash });
1066
1078
  const localnetStatus = transaction2.status === "ACTIVATED" ? "PENDING" /* PENDING */ : transaction2.status;
1067
- transaction2.status = Number(_chunkH4ZYXVV2cjs.transactionsStatusNameToNumber[localnetStatus]);
1079
+ transaction2.status = Number(_chunkFPZNF3JHcjs.transactionsStatusNameToNumber[localnetStatus]);
1068
1080
  transaction2.statusName = localnetStatus;
1069
1081
  return decodeLocalnetTransaction(transaction2);
1070
1082
  }
1071
1083
  const transaction = await publicClient.readContract({
1072
- address: _optionalChain([client, 'access', _32 => _32.chain, 'access', _33 => _33.consensusDataContract, 'optionalAccess', _34 => _34.address]),
1073
- abi: _optionalChain([client, 'access', _35 => _35.chain, 'access', _36 => _36.consensusDataContract, 'optionalAccess', _37 => _37.abi]),
1084
+ address: _optionalChain([client, 'access', _35 => _35.chain, 'access', _36 => _36.consensusDataContract, 'optionalAccess', _37 => _37.address]),
1085
+ abi: _optionalChain([client, 'access', _38 => _38.chain, 'access', _39 => _39.consensusDataContract, 'optionalAccess', _40 => _40.abi]),
1074
1086
  functionName: "getTransactionData",
1075
1087
  args: [
1076
1088
  hash,
@@ -1079,6 +1091,19 @@ var transactionActions = (client, publicClient) => ({
1079
1091
  ]
1080
1092
  });
1081
1093
  return decodeTransaction(transaction);
1094
+ },
1095
+ estimateTransactionGas: async (transactionParams) => {
1096
+ const formattedParams = {
1097
+ from: transactionParams.from || _optionalChain([client, 'access', _41 => _41.account, 'optionalAccess', _42 => _42.address]),
1098
+ to: transactionParams.to,
1099
+ data: transactionParams.data || "0x",
1100
+ value: transactionParams.value ? `0x${transactionParams.value.toString(16)}` : "0x0"
1101
+ };
1102
+ const gasHex = await client.request({
1103
+ method: "eth_estimateGas",
1104
+ params: [formattedParams]
1105
+ });
1106
+ return BigInt(gasHex);
1082
1107
  }
1083
1108
  });
1084
1109
 
@@ -1111,7 +1136,7 @@ var connect = async (client, network = "studionet", snapSource = "npm") => {
1111
1136
  chainName: selectedNetwork.name,
1112
1137
  rpcUrls: selectedNetwork.rpcUrls.default.http,
1113
1138
  nativeCurrency: selectedNetwork.nativeCurrency,
1114
- blockExplorerUrls: [_optionalChain([selectedNetwork, 'access', _38 => _38.blockExplorers, 'optionalAccess', _39 => _39.default, 'access', _40 => _40.url])]
1139
+ blockExplorerUrls: [_optionalChain([selectedNetwork, 'access', _43 => _43.blockExplorers, 'optionalAccess', _44 => _44.default, 'access', _45 => _45.url])]
1115
1140
  };
1116
1141
  const currentChainId = await window.ethereum.request({ method: "eth_chainId" });
1117
1142
  if (currentChainId !== chainIdHex) {
@@ -1145,10 +1170,10 @@ var metamaskClient = async (snapSource = "npm") => {
1145
1170
  }
1146
1171
  const isFlask = async () => {
1147
1172
  try {
1148
- const clientVersion = await _optionalChain([window, 'access', _41 => _41.ethereum, 'optionalAccess', _42 => _42.request, 'call', _43 => _43({
1173
+ const clientVersion = await _optionalChain([window, 'access', _46 => _46.ethereum, 'optionalAccess', _47 => _47.request, 'call', _48 => _48({
1149
1174
  method: "web3_clientVersion"
1150
1175
  })]);
1151
- return _optionalChain([clientVersion, 'optionalAccess', _44 => _44.includes, 'call', _45 => _45("flask")]);
1176
+ return _optionalChain([clientVersion, 'optionalAccess', _49 => _49.includes, 'call', _50 => _50("flask")]);
1152
1177
  } catch (error) {
1153
1178
  console.error("Error detecting Flask:", error);
1154
1179
  return false;
@@ -1156,7 +1181,7 @@ var metamaskClient = async (snapSource = "npm") => {
1156
1181
  };
1157
1182
  const installedSnaps = async () => {
1158
1183
  try {
1159
- return await _optionalChain([window, 'access', _46 => _46.ethereum, 'optionalAccess', _47 => _47.request, 'call', _48 => _48({
1184
+ return await _optionalChain([window, 'access', _51 => _51.ethereum, 'optionalAccess', _52 => _52.request, 'call', _53 => _53({
1160
1185
  method: "wallet_getSnaps"
1161
1186
  })]);
1162
1187
  } catch (error) {
@@ -1191,10 +1216,10 @@ function walletActions(client) {
1191
1216
  function chainActions(client) {
1192
1217
  return {
1193
1218
  initializeConsensusSmartContract: async (forceReset = false) => {
1194
- if (_optionalChain([client, 'access', _49 => _49.chain, 'optionalAccess', _50 => _50.id]) === _chunkZKBMABRAcjs.testnetAsimov.id) {
1219
+ if (_optionalChain([client, 'access', _54 => _54.chain, 'optionalAccess', _55 => _55.id]) === _chunkZKBMABRAcjs.testnetAsimov.id) {
1195
1220
  return;
1196
1221
  }
1197
- if (!forceReset && _optionalChain([client, 'access', _51 => _51.chain, 'access', _52 => _52.consensusMainContract, 'optionalAccess', _53 => _53.address]) && _optionalChain([client, 'access', _54 => _54.chain, 'access', _55 => _55.consensusMainContract, 'optionalAccess', _56 => _56.abi])) {
1222
+ if (!forceReset && _optionalChain([client, 'access', _56 => _56.chain, 'access', _57 => _57.consensusMainContract, 'optionalAccess', _58 => _58.address]) && _optionalChain([client, 'access', _59 => _59.chain, 'access', _60 => _60.consensusMainContract, 'optionalAccess', _61 => _61.abi])) {
1198
1223
  return;
1199
1224
  }
1200
1225
  const contractsResponse = await fetch(client.chain.rpcUrls.default.http[0], {
@@ -1279,12 +1304,15 @@ var createClient = (config = { chain: _chunkZKBMABRAcjs.localnet }) => {
1279
1304
  ...config.account ? { account: config.account } : {}
1280
1305
  });
1281
1306
  const clientWithBasicActions = baseClient.extend(_viem.publicActions).extend(_viem.walletActions).extend((client) => accountActions(client));
1282
- const clientWithAllActions = {
1307
+ const clientWithTransactionActions = {
1283
1308
  ...clientWithBasicActions,
1284
- ...contractActions(clientWithBasicActions, publicClient),
1309
+ ...transactionActions(clientWithBasicActions, publicClient),
1285
1310
  ...chainActions(clientWithBasicActions),
1286
- ...walletActions(clientWithBasicActions),
1287
- ...transactionActions(clientWithBasicActions, publicClient)
1311
+ ...walletActions(clientWithBasicActions)
1312
+ };
1313
+ const clientWithAllActions = {
1314
+ ...clientWithTransactionActions,
1315
+ ...contractActions(clientWithTransactionActions, publicClient)
1288
1316
  };
1289
1317
  const finalClient = {
1290
1318
  ...clientWithAllActions,
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-BYSCF33g.cjs';
4
- import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement } from './index-CxNl4CK5.cjs';
4
+ import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement } from './index-tixobC8m.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-BYSCF33g.js';
4
- import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement } from './index-BnFbqUhu.js';
4
+ import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement } from './index-Rls_T310.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
@@ -6,11 +6,12 @@ import {
6
6
  } from "./chunk-GEN4SJ6K.js";
7
7
  import {
8
8
  CalldataAddress,
9
+ isDecidedState,
9
10
  transactionResultNumberToName,
10
11
  transactionsStatusNameToNumber,
11
12
  transactionsStatusNumberToName,
12
13
  voteTypeNumberToName
13
- } from "./chunk-GACCNOPJ.js";
14
+ } from "./chunk-47QDX7IX.js";
14
15
  import {
15
16
  __export
16
17
  } from "./chunk-MLKGABMK.js";
@@ -730,6 +731,18 @@ var _sendTransaction = async ({
730
731
  }
731
732
  const validatedSenderAccount = validateAccount(senderAccount);
732
733
  const nonce = await client.getCurrentNonce({ address: validatedSenderAccount.address });
734
+ let estimatedGas;
735
+ try {
736
+ estimatedGas = await client.estimateTransactionGas({
737
+ from: validatedSenderAccount.address,
738
+ to: client.chain.consensusMainContract?.address,
739
+ data: encodedData,
740
+ value
741
+ });
742
+ } catch (error) {
743
+ console.warn("Gas estimation failed, using fallback value:", error);
744
+ estimatedGas = 200000n;
745
+ }
733
746
  const transactionRequest = await client.prepareTransactionRequest({
734
747
  account: validatedSenderAccount,
735
748
  to: client.chain.consensusMainContract?.address,
@@ -737,7 +750,7 @@ var _sendTransaction = async ({
737
750
  type: "legacy",
738
751
  nonce: Number(nonce),
739
752
  value,
740
- gas: 21000n
753
+ gas: estimatedGas
741
754
  });
742
755
  if (validatedSenderAccount?.type !== "local") {
743
756
  const formattedRequest = {
@@ -1034,9 +1047,8 @@ var receiptActions = (client, publicClient) => ({
1034
1047
  throw new Error("Transaction not found");
1035
1048
  }
1036
1049
  const transactionStatusString = String(transaction.status);
1037
- const transactionStatusFinalized = transactionsStatusNameToNumber["FINALIZED" /* FINALIZED */];
1038
1050
  const requestedStatus = transactionsStatusNameToNumber[status];
1039
- if (transactionStatusString === requestedStatus || status === "ACCEPTED" /* ACCEPTED */ && transactionStatusString === transactionStatusFinalized) {
1051
+ if (transactionStatusString === requestedStatus || status === "ACCEPTED" /* ACCEPTED */ && isDecidedState(transactionStatusString)) {
1040
1052
  let finalTransaction = transaction;
1041
1053
  if (client.chain.id === localnet.id) {
1042
1054
  finalTransaction = decodeLocalnetTransaction(transaction);
@@ -1079,6 +1091,19 @@ var transactionActions = (client, publicClient) => ({
1079
1091
  ]
1080
1092
  });
1081
1093
  return decodeTransaction(transaction);
1094
+ },
1095
+ estimateTransactionGas: async (transactionParams) => {
1096
+ const formattedParams = {
1097
+ from: transactionParams.from || client.account?.address,
1098
+ to: transactionParams.to,
1099
+ data: transactionParams.data || "0x",
1100
+ value: transactionParams.value ? `0x${transactionParams.value.toString(16)}` : "0x0"
1101
+ };
1102
+ const gasHex = await client.request({
1103
+ method: "eth_estimateGas",
1104
+ params: [formattedParams]
1105
+ });
1106
+ return BigInt(gasHex);
1082
1107
  }
1083
1108
  });
1084
1109
 
@@ -1279,12 +1304,15 @@ var createClient = (config = { chain: localnet }) => {
1279
1304
  ...config.account ? { account: config.account } : {}
1280
1305
  });
1281
1306
  const clientWithBasicActions = baseClient.extend(publicActions).extend(walletActions2).extend((client) => accountActions(client));
1282
- const clientWithAllActions = {
1307
+ const clientWithTransactionActions = {
1283
1308
  ...clientWithBasicActions,
1284
- ...contractActions(clientWithBasicActions, publicClient),
1309
+ ...transactionActions(clientWithBasicActions, publicClient),
1285
1310
  ...chainActions(clientWithBasicActions),
1286
- ...walletActions(clientWithBasicActions),
1287
- ...transactionActions(clientWithBasicActions, publicClient)
1311
+ ...walletActions(clientWithBasicActions)
1312
+ };
1313
+ const clientWithAllActions = {
1314
+ ...clientWithTransactionActions,
1315
+ ...contractActions(clientWithTransactionActions, publicClient)
1288
1316
  };
1289
1317
  const finalClient = {
1290
1318
  ...clientWithAllActions,
@@ -10,7 +10,9 @@
10
10
 
11
11
 
12
12
 
13
- var _chunkH4ZYXVV2cjs = require('../chunk-H4ZYXVV2.cjs');
13
+
14
+
15
+ var _chunkFPZNF3JHcjs = require('../chunk-FPZNF3JH.cjs');
14
16
  require('../chunk-75ZPJI57.cjs');
15
17
 
16
18
 
@@ -24,4 +26,6 @@ require('../chunk-75ZPJI57.cjs');
24
26
 
25
27
 
26
28
 
27
- exports.CalldataAddress = _chunkH4ZYXVV2cjs.CalldataAddress; exports.TransactionHashVariant = _chunkH4ZYXVV2cjs.TransactionHashVariant; exports.TransactionResult = _chunkH4ZYXVV2cjs.TransactionResult; exports.TransactionResultNameToNumber = _chunkH4ZYXVV2cjs.TransactionResultNameToNumber; exports.TransactionStatus = _chunkH4ZYXVV2cjs.TransactionStatus; exports.VoteType = _chunkH4ZYXVV2cjs.VoteType; exports.transactionResultNumberToName = _chunkH4ZYXVV2cjs.transactionResultNumberToName; exports.transactionsStatusNameToNumber = _chunkH4ZYXVV2cjs.transactionsStatusNameToNumber; exports.transactionsStatusNumberToName = _chunkH4ZYXVV2cjs.transactionsStatusNumberToName; exports.voteTypeNameToNumber = _chunkH4ZYXVV2cjs.voteTypeNameToNumber; exports.voteTypeNumberToName = _chunkH4ZYXVV2cjs.voteTypeNumberToName;
29
+
30
+
31
+ exports.CalldataAddress = _chunkFPZNF3JHcjs.CalldataAddress; exports.DECIDED_STATES = _chunkFPZNF3JHcjs.DECIDED_STATES; exports.TransactionHashVariant = _chunkFPZNF3JHcjs.TransactionHashVariant; exports.TransactionResult = _chunkFPZNF3JHcjs.TransactionResult; exports.TransactionResultNameToNumber = _chunkFPZNF3JHcjs.TransactionResultNameToNumber; exports.TransactionStatus = _chunkFPZNF3JHcjs.TransactionStatus; exports.VoteType = _chunkFPZNF3JHcjs.VoteType; exports.isDecidedState = _chunkFPZNF3JHcjs.isDecidedState; exports.transactionResultNumberToName = _chunkFPZNF3JHcjs.transactionResultNumberToName; exports.transactionsStatusNameToNumber = _chunkFPZNF3JHcjs.transactionsStatusNameToNumber; exports.transactionsStatusNumberToName = _chunkFPZNF3JHcjs.transactionsStatusNumberToName; exports.voteTypeNameToNumber = _chunkFPZNF3JHcjs.voteTypeNameToNumber; exports.voteTypeNumberToName = _chunkFPZNF3JHcjs.voteTypeNumberToName;
@@ -1,3 +1,3 @@
1
1
  export { Account, Address } from 'viem';
2
- export { d as CalldataAddress, C as CalldataEncodable, i as ContractMethod, h as ContractMethodBase, f as ContractParamsArraySchemaElement, g as ContractParamsSchema, j as ContractSchema, a as DecodedCallData, D as DecodedDeployData, G as GenLayerClient, e as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, M as MethodDescription, N as Network, S as SnapSource, k as TransactionHash, s as TransactionHashVariant, m as TransactionResult, p as TransactionResultNameToNumber, l as TransactionStatus, r as TransactionType, V as VoteType, o as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, q as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-CxNl4CK5.cjs';
2
+ export { 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, G as GenLayerClient, e as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, M as MethodDescription, N as Network, S as SnapSource, k as TransactionHash, w as TransactionHashVariant, m as TransactionResult, r as TransactionResultNameToNumber, l as TransactionStatus, u as TransactionType, V as VoteType, p as isDecidedState, q as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, s as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-tixobC8m.cjs';
3
3
  export { G as GenLayerChain } from '../chains-BYSCF33g.cjs';
@@ -1,3 +1,3 @@
1
1
  export { Account, Address } from 'viem';
2
- export { d as CalldataAddress, C as CalldataEncodable, i as ContractMethod, h as ContractMethodBase, f as ContractParamsArraySchemaElement, g as ContractParamsSchema, j as ContractSchema, a as DecodedCallData, D as DecodedDeployData, G as GenLayerClient, e as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, M as MethodDescription, N as Network, S as SnapSource, k as TransactionHash, s as TransactionHashVariant, m as TransactionResult, p as TransactionResultNameToNumber, l as TransactionStatus, r as TransactionType, V as VoteType, o as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, q as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-BnFbqUhu.js';
2
+ export { 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, G as GenLayerClient, e as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, M as MethodDescription, N as Network, S as SnapSource, k as TransactionHash, w as TransactionHashVariant, m as TransactionResult, r as TransactionResultNameToNumber, l as TransactionStatus, u as TransactionType, V as VoteType, p as isDecidedState, q as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, s as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-Rls_T310.js';
3
3
  export { G as GenLayerChain } from '../chains-BYSCF33g.js';
@@ -1,24 +1,28 @@
1
1
  import {
2
2
  CalldataAddress,
3
+ DECIDED_STATES,
3
4
  TransactionHashVariant,
4
5
  TransactionResult,
5
6
  TransactionResultNameToNumber,
6
7
  TransactionStatus,
7
8
  VoteType,
9
+ isDecidedState,
8
10
  transactionResultNumberToName,
9
11
  transactionsStatusNameToNumber,
10
12
  transactionsStatusNumberToName,
11
13
  voteTypeNameToNumber,
12
14
  voteTypeNumberToName
13
- } from "../chunk-GACCNOPJ.js";
15
+ } from "../chunk-47QDX7IX.js";
14
16
  import "../chunk-MLKGABMK.js";
15
17
  export {
16
18
  CalldataAddress,
19
+ DECIDED_STATES,
17
20
  TransactionHashVariant,
18
21
  TransactionResult,
19
22
  TransactionResultNameToNumber,
20
23
  TransactionStatus,
21
24
  VoteType,
25
+ isDecidedState,
22
26
  transactionResultNumberToName,
23
27
  transactionsStatusNameToNumber,
24
28
  transactionsStatusNumberToName,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "genlayer-js",
3
3
  "type": "module",
4
- "version": "0.18.0",
4
+ "version": "0.18.2",
5
5
  "description": "GenLayer JavaScript SDK",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -106,13 +106,18 @@ export const createClient = (config: ClientConfig = {chain: localnet}): GenLayer
106
106
  .extend(walletActions)
107
107
  .extend(client => accountActions(client as unknown as GenLayerClient<GenLayerChain>));
108
108
 
109
- // Create a client with all actions except transaction actions
110
- const clientWithAllActions = {
109
+ // First add transaction actions, then contract actions that depend on them
110
+ const clientWithTransactionActions = {
111
111
  ...clientWithBasicActions,
112
- ...contractActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>, publicClient),
112
+ ...transactionActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>, publicClient),
113
113
  ...chainActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>),
114
114
  ...genlayerWalletActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>),
115
- ...transactionActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>, publicClient),
115
+ } as unknown as GenLayerClient<GenLayerChain>;
116
+
117
+ // Then add contract actions that can now access transaction actions
118
+ const clientWithAllActions = {
119
+ ...clientWithTransactionActions,
120
+ ...contractActions(clientWithTransactionActions as unknown as GenLayerClient<GenLayerChain>, publicClient),
116
121
  } as unknown as GenLayerClient<GenLayerChain>;
117
122
 
118
123
  // Add transaction actions last, after all other actions are in place
@@ -303,6 +303,18 @@ const _sendTransaction = async ({
303
303
  const validatedSenderAccount = validateAccount(senderAccount);
304
304
 
305
305
  const nonce = await client.getCurrentNonce({address: validatedSenderAccount.address});
306
+ let estimatedGas: bigint;
307
+ try {
308
+ estimatedGas = await client.estimateTransactionGas({
309
+ from: validatedSenderAccount.address,
310
+ to: client.chain.consensusMainContract?.address as Address,
311
+ data: encodedData,
312
+ value: value,
313
+ });
314
+ } catch (error) {
315
+ console.warn("Gas estimation failed, using fallback value:", error);
316
+ estimatedGas = 200_000n;
317
+ }
306
318
  const transactionRequest = await client.prepareTransactionRequest({
307
319
  account: validatedSenderAccount,
308
320
  to: client.chain.consensusMainContract?.address as Address,
@@ -310,7 +322,7 @@ const _sendTransaction = async ({
310
322
  type: "legacy",
311
323
  nonce: Number(nonce),
312
324
  value: value,
313
- gas: 21000n,
325
+ gas: estimatedGas,
314
326
  });
315
327
 
316
328
  if (validatedSenderAccount?.type !== "local") {
@@ -5,6 +5,7 @@ import {
5
5
  GenLayerTransaction,
6
6
  GenLayerRawTransaction,
7
7
  transactionsStatusNameToNumber,
8
+ isDecidedState,
8
9
  } from "../types/transactions";
9
10
  import {transactionsConfig} from "../config/transactions";
10
11
  import {sleep} from "../utils/async";
@@ -37,11 +38,10 @@ export const receiptActions = (client: GenLayerClient<GenLayerChain>, publicClie
37
38
  throw new Error("Transaction not found");
38
39
  }
39
40
  const transactionStatusString = String(transaction.status);
40
- const transactionStatusFinalized = transactionsStatusNameToNumber[TransactionStatus.FINALIZED];
41
41
  const requestedStatus = transactionsStatusNameToNumber[status];
42
42
  if (
43
43
  transactionStatusString === requestedStatus ||
44
- (status === TransactionStatus.ACCEPTED && transactionStatusString === transactionStatusFinalized)
44
+ (status === TransactionStatus.ACCEPTED && isDecidedState(transactionStatusString))
45
45
  ) {
46
46
  let finalTransaction = transaction;
47
47
  if (client.chain.id === localnet.id) {
@@ -90,6 +90,26 @@ export const transactionActions = (client: GenLayerClient<GenLayerChain>, public
90
90
  })) as unknown as GenLayerRawTransaction;
91
91
  return decodeTransaction(transaction);
92
92
  },
93
+ estimateTransactionGas: async (transactionParams: {
94
+ from?: Address;
95
+ to: Address;
96
+ data?: `0x${string}`;
97
+ value?: bigint;
98
+ }): Promise<bigint> => {
99
+ const formattedParams = {
100
+ from: transactionParams.from || client.account?.address,
101
+ to: transactionParams.to,
102
+ data: transactionParams.data || "0x",
103
+ value: transactionParams.value ? `0x${transactionParams.value.toString(16)}` as `0x${string}` : "0x0" as `0x${string}`,
104
+ };
105
+
106
+ const gasHex = await client.request({
107
+ method: "eth_estimateGas",
108
+ params: [formattedParams],
109
+ }) as string;
110
+
111
+ return BigInt(gasHex);
112
+ },
93
113
  });
94
114
 
95
115
 
@@ -1,5 +1,4 @@
1
- import {GenLayerTransaction, GenLayerRawTransaction, DecodedCallData, DecodedDeployData} from "../types/transactions";
2
- import {transactionsStatusNumberToName, transactionResultNumberToName, voteTypeNumberToName, VoteType} from "../types/transactions";
1
+ import {GenLayerTransaction, GenLayerRawTransaction, DecodedCallData, DecodedDeployData,transactionsStatusNumberToName, transactionResultNumberToName, voteTypeNumberToName, VoteType} from "../types/transactions";
3
2
  import {b64ToArray, calldataToUserFriendlyJson, resultToUserFriendlyJson} from "../utils/jsonifier";
4
3
  import {fromRlp, fromHex, Hex, Address} from "viem";
5
4
  import * as calldataAbi from "../abi/calldata";
@@ -18,6 +18,7 @@ export type GenLayerMethod =
18
18
  | {method: "gen_getContractCode"; params: [address: Address]}
19
19
  | {method: "sim_getTransactionsForAddress"; params: [address: Address, filter?: "all" | "from" | "to"]}
20
20
  | {method: "eth_getTransactionCount"; params: [address: Address, block: string]}
21
+ | {method: "eth_estimateGas"; params: [transactionParams: any]}
21
22
  | {method: "gen_call"; params: [requestParams: any]};
22
23
 
23
24
  /*
@@ -80,6 +81,12 @@ export type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<
80
81
  }) => Promise<`0x${string}`>;
81
82
  getTransaction: (args: {hash: TransactionHash}) => Promise<GenLayerTransaction>;
82
83
  getCurrentNonce: (args: {address: Address}) => Promise<number>;
84
+ estimateTransactionGas: (transactionParams: {
85
+ from?: Address;
86
+ to: Address;
87
+ data?: `0x${string}`;
88
+ value?: bigint;
89
+ }) => Promise<bigint>;
83
90
  waitForTransactionReceipt: (args: {
84
91
  hash: TransactionHash;
85
92
  status?: TransactionStatus;
@@ -71,6 +71,21 @@ export const transactionsStatusNameToNumber = {
71
71
  [TransactionStatus.LEADER_TIMEOUT]: "13",
72
72
  };
73
73
 
74
+ export const DECIDED_STATES = [
75
+ TransactionStatus.ACCEPTED,
76
+ TransactionStatus.UNDETERMINED,
77
+ TransactionStatus.LEADER_TIMEOUT,
78
+ TransactionStatus.VALIDATORS_TIMEOUT,
79
+ TransactionStatus.CANCELED,
80
+ TransactionStatus.FINALIZED
81
+ ];
82
+
83
+ export function isDecidedState(status: string): boolean {
84
+ return DECIDED_STATES.some(state =>
85
+ transactionsStatusNameToNumber[state] === status
86
+ );
87
+ }
88
+
74
89
  export const transactionResultNumberToName = {
75
90
  "0": TransactionResult.IDLE,
76
91
  "1": TransactionResult.AGREE,
@@ -0,0 +1,142 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { TransactionStatus, DECIDED_STATES, isDecidedState } from "../src/types/transactions";
3
+ import { receiptActions } from "../src/transactions/actions";
4
+ import { localnet } from "../src/chains/localnet";
5
+
6
+ const mockFetch = vi.fn();
7
+ vi.stubGlobal("fetch", mockFetch);
8
+
9
+ describe("DECIDED_STATES constant", () => {
10
+ it("should contain all expected decided states", () => {
11
+ const expectedStates = [
12
+ TransactionStatus.ACCEPTED,
13
+ TransactionStatus.UNDETERMINED,
14
+ TransactionStatus.LEADER_TIMEOUT,
15
+ TransactionStatus.VALIDATORS_TIMEOUT,
16
+ TransactionStatus.CANCELED,
17
+ TransactionStatus.FINALIZED
18
+ ];
19
+
20
+ expect(DECIDED_STATES).toEqual(expectedStates);
21
+ });
22
+ });
23
+
24
+ describe("isDecidedState utility function", () => {
25
+ it("should return true for all decided states", () => {
26
+ const decidedStatusNumbers = ["5", "6", "13", "12", "8", "7"]; // ACCEPTED, UNDETERMINED, LEADER_TIMEOUT, VALIDATORS_TIMEOUT, CANCELED, FINALIZED
27
+
28
+ decidedStatusNumbers.forEach(statusNum => {
29
+ expect(isDecidedState(statusNum)).toBe(true);
30
+ });
31
+ });
32
+
33
+ it("should return false for non-decided states", () => {
34
+ const nonDecidedStatusNumbers = ["0", "1", "2", "3", "4", "9", "10", "11"]; // UNINITIALIZED, PENDING, PROPOSING, COMMITTING, REVEALING, APPEAL_REVEALING, APPEAL_COMMITTING, READY_TO_FINALIZE
35
+
36
+ nonDecidedStatusNumbers.forEach(statusNum => {
37
+ expect(isDecidedState(statusNum)).toBe(false);
38
+ });
39
+ });
40
+
41
+ it("should return false for invalid statuses", () => {
42
+ const invalidStatuses = ["999", "invalid", ""];
43
+
44
+ invalidStatuses.forEach(status => {
45
+ expect(isDecidedState(status)).toBe(false);
46
+ });
47
+ });
48
+ });
49
+
50
+ describe("waitForTransactionReceipt with DECIDED_STATES", () => {
51
+ beforeEach(() => {
52
+ mockFetch.mockReset();
53
+ });
54
+
55
+ it("should accept all decided states when waiting for ACCEPTED", async () => {
56
+ const decidedStatusNumbers = ["5", "6", "13", "12", "8", "7"]; // All decided states
57
+
58
+ for (const statusNum of decidedStatusNumbers) {
59
+ const mockTransaction = {
60
+ hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6",
61
+ status: statusNum,
62
+ from_address: "0x123",
63
+ to_address: "0x456",
64
+ value: "0",
65
+ gaslimit: "1000000",
66
+ nonce: "1",
67
+ created_at: "2023-01-01T00:00:00Z",
68
+ };
69
+
70
+ const mockClient = {
71
+ chain: localnet,
72
+ getTransaction: vi.fn().mockResolvedValue(mockTransaction)
73
+ };
74
+
75
+ const mockPublicClient = {} as any;
76
+
77
+ const actions = receiptActions(mockClient as any, mockPublicClient);
78
+ const result = await actions.waitForTransactionReceipt({
79
+ hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6" as any,
80
+ status: TransactionStatus.ACCEPTED,
81
+ });
82
+
83
+ expect(result).toEqual(mockTransaction);
84
+ }
85
+ });
86
+
87
+ it("should not affect waiting for specific non-ACCEPTED statuses", async () => {
88
+ const mockTransaction = {
89
+ hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6",
90
+ status: "7", // FINALIZED
91
+ from_address: "0x123",
92
+ to_address: "0x456",
93
+ value: "0",
94
+ gaslimit: "1000000",
95
+ nonce: "1",
96
+ created_at: "2023-01-01T00:00:00Z",
97
+ };
98
+
99
+ const mockClient = {
100
+ chain: localnet,
101
+ getTransaction: vi.fn().mockResolvedValue(mockTransaction)
102
+ };
103
+
104
+ const mockPublicClient = {} as any;
105
+
106
+ const actions = receiptActions(mockClient as any, mockPublicClient);
107
+ const result = await actions.waitForTransactionReceipt({
108
+ hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6" as any,
109
+ status: TransactionStatus.FINALIZED,
110
+ });
111
+
112
+ expect(result).toEqual(mockTransaction);
113
+ });
114
+
115
+ it("should maintain backward compatibility", async () => {
116
+ const mockTransaction = {
117
+ hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6",
118
+ status: "5", // ACCEPTED
119
+ from_address: "0x123",
120
+ to_address: "0x456",
121
+ value: "0",
122
+ gaslimit: "1000000",
123
+ nonce: "1",
124
+ created_at: "2023-01-01T00:00:00Z",
125
+ };
126
+
127
+ const mockClient = {
128
+ chain: localnet,
129
+ getTransaction: vi.fn().mockResolvedValue(mockTransaction)
130
+ };
131
+
132
+ const mockPublicClient = {} as any;
133
+
134
+ const actions = receiptActions(mockClient as any, mockPublicClient);
135
+ const result = await actions.waitForTransactionReceipt({
136
+ hash: "0x4b8037744adab7ea8335b4f839979d20031d83a8ccdf706e0ae61312930335f6" as any,
137
+ status: TransactionStatus.ACCEPTED,
138
+ });
139
+
140
+ expect(result).toEqual(mockTransaction);
141
+ });
142
+ });