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.
- package/CHANGELOG.md +9 -0
- package/dist/{index-TWCEN45Z.d.ts → index-CgHl4W-5.d.ts} +1 -1
- package/dist/{index-icLJcrDm.d.cts → index-IViMPpkl.d.cts} +1 -1
- package/dist/index.cjs +107 -99
- package/dist/index.d.cts +13 -4
- package/dist/index.d.ts +13 -4
- package/dist/index.js +105 -97
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/abi/calldata/encoder.ts +36 -0
- package/src/contracts/actions.ts +4 -40
- package/src/index.ts +6 -0
- package/src/transactions/actions.ts +6 -280
- package/src/transactions/decoders.ts +276 -0
package/dist/types/index.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Account, Address } from 'viem';
|
|
2
|
-
export {
|
|
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';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Account, Address } from 'viem';
|
|
2
|
-
export {
|
|
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
|
@@ -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
|
+
}
|
package/src/contracts/actions.ts
CHANGED
|
@@ -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 {
|
|
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 =
|
|
48
|
+
finalTransaction = decodeLocalnetTransaction(transaction as unknown as GenLayerTransaction);
|
|
75
49
|
}
|
|
76
50
|
if (!fullTransaction) {
|
|
77
|
-
return
|
|
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
|
|
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
|
|
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
|
-
};
|