genlayer-js 0.13.0 → 0.14.1

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.
@@ -1,3 +1,3 @@
1
1
  export { Account, Address } from 'viem';
2
- export { a as CalldataAddress, C as CalldataEncodable, f as ContractMethod, e as ContractMethodBase, c as ContractParamsArraySchemaElement, d as ContractParamsSchema, g as ContractSchema, q as DecodedCallData, D as DecodedDeployData, G as GenLayerClient, b as GenLayerMethod, s as GenLayerRawTransaction, r as GenLayerTransaction, H as Hash, M as MethodDescription, N as Network, S as SnapSource, h as TransactionHash, p as TransactionHashVariant, j as TransactionResult, m as TransactionResultNameToNumber, i as TransactionStatus, o as TransactionType, V as VoteType, l as transactionResultNumberToName, k as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, n as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-icLJcrDm.cjs';
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-IViMPpkl.cjs';
3
3
  export { G as GenLayerChain } from '../chains-BYSCF33g.cjs';
@@ -1,3 +1,3 @@
1
1
  export { Account, Address } from 'viem';
2
- export { a as CalldataAddress, C as CalldataEncodable, f as ContractMethod, e as ContractMethodBase, c as ContractParamsArraySchemaElement, d as ContractParamsSchema, g as ContractSchema, q as DecodedCallData, D as DecodedDeployData, G as GenLayerClient, b as GenLayerMethod, s as GenLayerRawTransaction, r as GenLayerTransaction, H as Hash, M as MethodDescription, N as Network, S as SnapSource, h as TransactionHash, p as TransactionHashVariant, j as TransactionResult, m as TransactionResultNameToNumber, i as TransactionStatus, o as TransactionType, V as VoteType, l as transactionResultNumberToName, k as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, n as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-TWCEN45Z.js';
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-CgHl4W-5.js';
3
3
  export { G as GenLayerChain } from '../chains-BYSCF33g.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "genlayer-js",
3
3
  "type": "module",
4
- "version": "0.13.0",
4
+ "version": "0.14.1",
5
5
  "description": "GenLayer JavaScript SDK",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -140,3 +140,39 @@ export function encode(data: CalldataEncodable): Uint8Array {
140
140
  encodeImpl(arr, data);
141
141
  return new Uint8Array(arr);
142
142
  }
143
+
144
+ // Constructs a calldata object for contract calls, omitting empty args/kwargs for compactness.
145
+ export function makeCalldataObject(
146
+ method: string | undefined,
147
+ args: CalldataEncodable[] | undefined,
148
+ kwargs: {[key: string]: CalldataEncodable} | Map<string, CalldataEncodable> | undefined,
149
+ ): CalldataEncodable {
150
+ let ret: {[key: string]: CalldataEncodable} = {};
151
+
152
+ if (method) {
153
+ ret["method"] = method;
154
+ }
155
+
156
+ if (args && args.length > 0) {
157
+ ret["args"] = args;
158
+ }
159
+
160
+ if (kwargs) {
161
+ if (kwargs instanceof Map) {
162
+ if (kwargs.size > 0) {
163
+ ret["kwargs"] = kwargs;
164
+ }
165
+ } else {
166
+ let hasVal = false;
167
+ for (const _k in kwargs) {
168
+ hasVal = true;
169
+ break;
170
+ }
171
+ if (hasVal) {
172
+ ret["kwargs"] = kwargs;
173
+ }
174
+ }
175
+ }
176
+
177
+ return ret;
178
+ }
@@ -12,43 +12,6 @@ import {
12
12
  } from "@/types";
13
13
  import {fromHex, toHex, zeroAddress, encodeFunctionData, PublicClient, parseEventLogs} from "viem";
14
14
 
15
- function makeCalldataObject(
16
- method: string | undefined,
17
- args: CalldataEncodable[] | undefined,
18
- kwargs: {[key: string]: CalldataEncodable} | Map<string, CalldataEncodable> | undefined,
19
- ): CalldataEncodable {
20
- // this method omits args or kwargs if they are empty
21
- // it reduces transaction size
22
- let ret: {[key: string]: CalldataEncodable} = {};
23
-
24
- if (method) {
25
- ret["method"] = method;
26
- }
27
-
28
- if (args && args.length > 0) {
29
- ret["args"] = args;
30
- }
31
-
32
- if (kwargs) {
33
- if (kwargs instanceof Map) {
34
- if (kwargs.size > 0) {
35
- ret["kwargs"] = kwargs;
36
- }
37
- } else {
38
- let hasVal = false;
39
- for (const _k in kwargs) {
40
- hasVal = true;
41
- break;
42
- }
43
- if (hasVal) {
44
- ret["kwargs"] = kwargs;
45
- }
46
- }
47
- }
48
-
49
- return ret;
50
- }
51
-
52
15
  export const contractActions = (client: GenLayerClient<GenLayerChain>, publicClient: PublicClient) => {
53
16
  return {
54
17
  getContractSchema: async (address: Address): Promise<ContractSchema> => {
@@ -91,7 +54,7 @@ export const contractActions = (client: GenLayerClient<GenLayerChain>, publicCli
91
54
  transactionHashVariant = TransactionHashVariant.LATEST_NONFINAL,
92
55
  } = args;
93
56
 
94
- const encodedData = [calldata.encode(makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
57
+ const encodedData = [calldata.encode(calldata.makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
95
58
  const serializedData = serialize(encodedData);
96
59
 
97
60
  const senderAddress = account?.address ?? client.account?.address;
@@ -135,7 +98,7 @@ export const contractActions = (client: GenLayerClient<GenLayerChain>, publicCli
135
98
  leaderOnly = false,
136
99
  consensusMaxRotations = client.chain.defaultConsensusMaxRotations,
137
100
  } = args;
138
- const data = [calldata.encode(makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
101
+ const data = [calldata.encode(calldata.makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
139
102
  const serializedData = serialize(data);
140
103
  const senderAccount = account || client.account;
141
104
  const encodedData = _encodeAddTransactionData({
@@ -171,7 +134,7 @@ export const contractActions = (client: GenLayerClient<GenLayerChain>, publicCli
171
134
  } = args;
172
135
  const data = [
173
136
  code,
174
- calldata.encode(makeCalldataObject(undefined, constructorArgs, kwargs)),
137
+ calldata.encode(calldata.makeCalldataObject(undefined, constructorArgs, kwargs)),
175
138
  leaderOnly,
176
139
  ];
177
140
  const serializedData = serialize(data);
@@ -284,6 +247,7 @@ const _sendTransaction = async ({
284
247
  type: "legacy",
285
248
  nonce: Number(nonce),
286
249
  value: value,
250
+ gas: 21000n,
287
251
  });
288
252
 
289
253
  if (validatedSenderAccount?.type !== "local") {
package/src/index.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  // src/index.ts
2
2
  export {createClient} from "./client/client";
3
3
  export {createAccount, generatePrivateKey} from "./accounts/account";
4
+ export {
5
+ decodeInputData,
6
+ decodeTransaction,
7
+ simplifyTransactionReceipt,
8
+ decodeLocalnetTransaction
9
+ } from "./transactions/decoders";
4
10
  export * as chains from "./chains";
5
11
  export * as abi from "./abi";
@@ -5,41 +5,15 @@ import {
5
5
  GenLayerTransaction,
6
6
  GenLayerRawTransaction,
7
7
  transactionsStatusNameToNumber,
8
- transactionsStatusNumberToName,
9
- transactionResultNumberToName,
10
- VoteType,
11
- voteTypeNumberToName,
12
- DecodedCallData,
13
- DecodedDeployData,
14
8
  } from "../types/transactions";
15
9
  import {transactionsConfig} from "../config/transactions";
16
10
  import {sleep} from "../utils/async";
17
11
  import {GenLayerChain} from "@/types";
18
- import {b64ToArray, calldataToUserFriendlyJson, resultToUserFriendlyJson} from "@/utils/jsonifier";
19
- import {Abi, PublicClient, fromRlp, fromHex, Hex, Address} from "viem";
20
- import * as calldataAbi from "@/abi/calldata";
12
+ import {Abi, PublicClient, Address} from "viem";
21
13
  import {localnet} from "@/chains/localnet";
14
+ import {decodeLocalnetTransaction, decodeTransaction, simplifyTransactionReceipt} from "./decoders";
22
15
 
23
- // Fields to remove from simplified transaction receipts
24
- const FIELDS_TO_REMOVE = [
25
- "raw", "contract_state", "base64", "consensus_history", "tx_data",
26
- "eq_blocks_outputs", "r", "s", "v", "created_timestamp",
27
- "current_timestamp", "tx_execution_hash", "random_seed", "states",
28
- "contract_code", "appeal_failed", "appeal_leader_timeout",
29
- "appeal_processing_time", "appeal_undetermined", "appealed",
30
- "timestamp_appeal", "config_rotation_rounds", "rotation_count",
31
- "queue_position", "queue_type", "leader_timeout_validators",
32
- "triggered_by", "num_of_initial_validators",
33
- "timestamp_awaiting_finalization", "last_vote_timestamp",
34
- "read_state_block_range", "tx_slot", "blockHash", "blockNumber",
35
- "to", "transactionIndex"
36
- ];
37
16
 
38
- // Field name mappings for cross-language compatibility with genlayer-py
39
- const FIELD_NAME_MAPPINGS: Record<string, string> = {
40
- statusName: "status_name",
41
- typeHex: "type"
42
- };
43
17
 
44
18
  export const receiptActions = (client: GenLayerClient<GenLayerChain>, publicClient: PublicClient) => ({
45
19
  waitForTransactionReceipt: async ({
@@ -71,10 +45,10 @@ export const receiptActions = (client: GenLayerClient<GenLayerChain>, publicClie
71
45
  ) {
72
46
  let finalTransaction = transaction;
73
47
  if (client.chain.id === localnet.id) {
74
- finalTransaction = _decodeLocalnetTransaction(transaction as unknown as GenLayerTransaction);
48
+ finalTransaction = decodeLocalnetTransaction(transaction as unknown as GenLayerTransaction);
75
49
  }
76
50
  if (!fullTransaction) {
77
- return _simplifyTransactionReceipt(finalTransaction as GenLayerTransaction);
51
+ return simplifyTransactionReceipt(finalTransaction as GenLayerTransaction);
78
52
  }
79
53
  return finalTransaction;
80
54
  }
@@ -103,7 +77,7 @@ export const transactionActions = (client: GenLayerClient<GenLayerChain>, public
103
77
 
104
78
  transaction.status = Number(transactionsStatusNameToNumber[localnetStatus as TransactionStatus]);
105
79
  transaction.statusName = localnetStatus as TransactionStatus;
106
- return _decodeLocalnetTransaction(transaction as unknown as GenLayerTransaction);
80
+ return decodeLocalnetTransaction(transaction as unknown as GenLayerTransaction);
107
81
  }
108
82
  const transaction = (await publicClient.readContract({
109
83
  address: client.chain.consensusDataContract?.address as Address,
@@ -114,256 +88,8 @@ export const transactionActions = (client: GenLayerClient<GenLayerChain>, public
114
88
  Math.round(new Date().getTime() / 1000), // unix seconds
115
89
  ],
116
90
  })) as unknown as GenLayerRawTransaction;
117
- return _decodeTransaction(transaction);
91
+ return decodeTransaction(transaction);
118
92
  },
119
93
  });
120
94
 
121
- const _decodeInputData = (
122
- rlpEncodedAppData: Hex | undefined | null,
123
- recipient: Address,
124
- ): DecodedDeployData | DecodedCallData | null => {
125
- if (!rlpEncodedAppData || rlpEncodedAppData === "0x" || rlpEncodedAppData.length <= 2) {
126
- return null;
127
- }
128
- try {
129
- const rlpDecodedArray = fromRlp(rlpEncodedAppData) as Hex[];
130
95
 
131
- if (rlpDecodedArray.length === 3) {
132
- return {
133
- code: fromHex(rlpDecodedArray[0], "string") as `0x${string}`,
134
- constructorArgs:
135
- rlpDecodedArray[1] && rlpDecodedArray[1] !== "0x"
136
- ? calldataAbi.decode(fromHex(rlpDecodedArray[1], "bytes"))
137
- : null,
138
- leaderOnly: rlpDecodedArray[2] === "0x01",
139
- type: "deploy",
140
- contractAddress: recipient,
141
- };
142
- } else if (rlpDecodedArray.length === 2) {
143
- return {
144
- callData:
145
- rlpDecodedArray[0] && rlpDecodedArray[0] !== "0x"
146
- ? calldataAbi.decode(fromHex(rlpDecodedArray[0], "bytes"))
147
- : null,
148
- leaderOnly: rlpDecodedArray[1] === "0x01",
149
- type: "call",
150
- };
151
- } else {
152
- console.warn(
153
- "[decodeInputData] WRITE: Unexpected RLP array length:",
154
- rlpDecodedArray.length,
155
- rlpDecodedArray,
156
- );
157
- return null;
158
- }
159
- } catch (e) {
160
- console.error(
161
- "[decodeInputData] Error during comprehensive decoding:",
162
- e,
163
- "Raw RLP App Data:",
164
- rlpEncodedAppData,
165
- );
166
- return null;
167
- }
168
- };
169
-
170
- const _decodeTransaction = (tx: GenLayerRawTransaction): GenLayerTransaction => {
171
- const txDataDecoded = _decodeInputData(tx.txData, tx.recipient);
172
-
173
- const decodedTx = {
174
- ...tx,
175
- txData: tx.txData,
176
- txDataDecoded: txDataDecoded,
177
-
178
- currentTimestamp: tx.currentTimestamp.toString(),
179
- numOfInitialValidators: tx.numOfInitialValidators.toString(),
180
- txSlot: tx.txSlot.toString(),
181
- createdTimestamp: tx.createdTimestamp.toString(),
182
- lastVoteTimestamp: tx.lastVoteTimestamp.toString(),
183
- queuePosition: tx.queuePosition.toString(),
184
- numOfRounds: tx.numOfRounds.toString(),
185
-
186
- readStateBlockRange: {
187
- ...tx.readStateBlockRange,
188
- activationBlock: tx.readStateBlockRange.activationBlock.toString(),
189
- processingBlock: tx.readStateBlockRange.processingBlock.toString(),
190
- proposalBlock: tx.readStateBlockRange.proposalBlock.toString(),
191
- },
192
-
193
- statusName:
194
- transactionsStatusNumberToName[String(tx.status) as keyof typeof transactionsStatusNumberToName],
195
- resultName:
196
- transactionResultNumberToName[String(tx.result) as keyof typeof transactionResultNumberToName],
197
-
198
- lastRound: {
199
- ...tx.lastRound,
200
- round: tx.lastRound.round.toString(),
201
- leaderIndex: tx.lastRound.leaderIndex.toString(),
202
- votesCommitted: tx.lastRound.votesCommitted.toString(),
203
- votesRevealed: tx.lastRound.votesRevealed.toString(),
204
- appealBond: tx.lastRound.appealBond.toString(),
205
- rotationsLeft: tx.lastRound.rotationsLeft.toString(),
206
- validatorVotesName: tx.lastRound.validatorVotes.map(
207
- vote => voteTypeNumberToName[String(vote) as keyof typeof voteTypeNumberToName],
208
- ) as VoteType[],
209
- },
210
- };
211
- return decodedTx as GenLayerTransaction;
212
- };
213
-
214
- const _simplifyTransactionReceipt = (tx: GenLayerTransaction): GenLayerTransaction => {
215
- /**
216
- * Simplify transaction receipt by removing non-essential fields while preserving functionality.
217
- *
218
- * Removes: Binary data, internal timestamps, appeal fields, processing details, historical data
219
- * Preserves: Transaction IDs, status, execution results, node configs, readable data
220
- */
221
- const simplifyObject = (obj: any, path = ""): any => {
222
- if (obj === null || obj === undefined) return obj;
223
-
224
- if (Array.isArray(obj)) {
225
- return obj.map(item => simplifyObject(item, path)).filter(item => item !== undefined);
226
- }
227
-
228
- if (typeof obj === "object") {
229
- const result: any = {};
230
-
231
- for (const [key, value] of Object.entries(obj)) {
232
- const currentPath = path ? `${path}.${key}` : key;
233
-
234
- // Always remove these fields
235
- if (FIELDS_TO_REMOVE.includes(key)) {
236
- continue;
237
- }
238
-
239
- // Remove node_config only from top level (keep it in consensus_data)
240
- if (key === "node_config" && !path.includes("consensus_data")) {
241
- continue;
242
- }
243
-
244
- // Special handling for consensus_data - keep execution results and votes
245
- if (key === "consensus_data" && typeof value === "object" && value !== null) {
246
- const simplifiedConsensus: any = {};
247
-
248
- // Keep votes
249
- if ("votes" in value) {
250
- simplifiedConsensus.votes = value.votes;
251
- }
252
-
253
- // Process leader_receipt to keep only essential fields
254
- if ("leader_receipt" in value && Array.isArray(value.leader_receipt)) {
255
- simplifiedConsensus.leader_receipt = value.leader_receipt.map((receipt: any) => {
256
- const simplifiedReceipt: any = {};
257
-
258
- // Keep essential execution info
259
- ["execution_result", "genvm_result", "mode", "vote", "node_config"].forEach(field => {
260
- if (field in receipt) {
261
- simplifiedReceipt[field] = receipt[field];
262
- }
263
- });
264
-
265
- // Keep readable calldata
266
- if (receipt.calldata && typeof receipt.calldata === "object" && "readable" in receipt.calldata) {
267
- simplifiedReceipt.calldata = { readable: receipt.calldata.readable };
268
- }
269
-
270
- // Keep readable outputs
271
- if (receipt.eq_outputs) {
272
- simplifiedReceipt.eq_outputs = simplifyObject(receipt.eq_outputs, currentPath);
273
- }
274
- if (receipt.result) {
275
- simplifiedReceipt.result = simplifyObject(receipt.result, currentPath);
276
- }
277
-
278
- return simplifiedReceipt;
279
- });
280
- }
281
-
282
- // Process validators to keep execution results
283
- if ("validators" in value && Array.isArray(value.validators)) {
284
- const simplifiedValidators = value.validators.map((validator: any) => {
285
- const simplifiedValidator: any = {};
286
- ["execution_result", "genvm_result", "mode", "vote", "node_config"].forEach(field => {
287
- if (field in validator) {
288
- simplifiedValidator[field] = validator[field];
289
- }
290
- });
291
- return simplifiedValidator;
292
- }).filter((validator: any) => Object.keys(validator).length > 0);
293
-
294
- if (simplifiedValidators.length > 0) {
295
- simplifiedConsensus.validators = simplifiedValidators;
296
- }
297
- }
298
-
299
- result[key] = simplifiedConsensus;
300
- continue;
301
- }
302
-
303
- const simplifiedValue = simplifyObject(value, currentPath);
304
- // Include the value if it's not undefined and not an empty object
305
- // Special case: include numeric 0 values (like value: 0)
306
- const shouldInclude = simplifiedValue !== undefined &&
307
- !(typeof simplifiedValue === "object" && simplifiedValue !== null && Object.keys(simplifiedValue).length === 0);
308
-
309
- if (shouldInclude || simplifiedValue === 0) {
310
- // Map field names for cross-language compatibility
311
- const mappedKey = FIELD_NAME_MAPPINGS[key] || key;
312
- result[mappedKey] = simplifiedValue;
313
- }
314
- }
315
-
316
- return result;
317
- }
318
-
319
- return obj;
320
- };
321
-
322
- return simplifyObject({...tx});
323
- };
324
-
325
- const _decodeLocalnetTransaction = (tx: GenLayerTransaction): GenLayerTransaction => {
326
- if (!tx.data) return tx;
327
- try {
328
- const leaderReceipt = tx.consensus_data?.leader_receipt;
329
- if (leaderReceipt) {
330
- const receipts = Array.isArray(leaderReceipt) ? leaderReceipt : [leaderReceipt];
331
- receipts.forEach((receipt) => {
332
- if (receipt.result && typeof receipt.result === "string") {
333
- receipt.result = resultToUserFriendlyJson(receipt.result);
334
- }
335
- if (receipt.calldata && typeof receipt.calldata === "string") {
336
- receipt.calldata = {
337
- base64: receipt.calldata as string,
338
- ...calldataToUserFriendlyJson(b64ToArray(receipt.calldata as string)),
339
- };
340
- }
341
- if (receipt.eq_outputs) {
342
- const decodedOutputs: any = {};
343
- for (const [key, value] of Object.entries(receipt.eq_outputs)) {
344
- if (typeof value === "object" && value !== null) {
345
- decodedOutputs[key] = value;
346
- } else {
347
- try {
348
- decodedOutputs[key] = resultToUserFriendlyJson(value as string);
349
- } catch (e) {
350
- console.warn(`Error decoding eq_output ${key}: ${e}`);
351
- decodedOutputs[key] = value;
352
- }
353
- }
354
- }
355
- receipt.eq_outputs = decodedOutputs;
356
- }
357
- });
358
- }
359
- if (tx.data?.calldata && typeof tx.data.calldata === "string") {
360
- tx.data.calldata = {
361
- base64: tx.data.calldata as string,
362
- ...calldataToUserFriendlyJson(b64ToArray(tx.data.calldata as string)),
363
- };
364
- }
365
- } catch (e) {
366
- console.error("Error in _decodeLocalnetTransaction:", e);
367
- }
368
- return tx;
369
- };